diff --git a/bin/config/settings_zone.xml b/bin/config/settings_zone.xml index f50c18ce..547219a7 100644 --- a/bin/config/settings_zone.xml +++ b/bin/config/settings_zone.xml @@ -13,7 +13,7 @@ ./cache/ - 1 + true ../scripts/native/ ../cmake-build-debug/ cmake --build %1% --target %2% diff --git a/scripts/native/CmnDef/CmnDefCutSceneReplay.cpp b/scripts/native/CmnDef/CmnDefCutSceneReplay.cpp index 618c1610..39bf4300 100644 --- a/scripts/native/CmnDef/CmnDefCutSceneReplay.cpp +++ b/scripts/native/CmnDef/CmnDefCutSceneReplay.cpp @@ -3,7 +3,7 @@ class CmnDefCutSceneReplay : public EventScript { public: - CmnDefCutSceneReplay() : EventScript( "CmnDefCutSceneReplay", 721028 ) + CmnDefCutSceneReplay() : EventScript( 721028 ) {} void Scene00000( Entity::Player& player ) diff --git a/scripts/native/CmnDef/CmnDefInnBed.cpp b/scripts/native/CmnDef/CmnDefInnBed.cpp index 5e675b88..ac8a0a68 100644 --- a/scripts/native/CmnDef/CmnDefInnBed.cpp +++ b/scripts/native/CmnDef/CmnDefInnBed.cpp @@ -3,7 +3,7 @@ class CmnDefInnBed : public EventScript { public: - CmnDefInnBed() : EventScript( "CmnDefInnBed", 720916 ) + CmnDefInnBed() : EventScript( 720916 ) {} // menu diff --git a/scripts/native/CmnDef/CmnDefLinkShell.cpp b/scripts/native/CmnDef/CmnDefLinkShell.cpp index eb2a7b29..f0df71f9 100644 --- a/scripts/native/CmnDef/CmnDefLinkShell.cpp +++ b/scripts/native/CmnDef/CmnDefLinkShell.cpp @@ -7,7 +7,7 @@ class CmnDefLinkShell : public EventScript { public: - CmnDefLinkShell() : EventScript( "CmnDefLinkShell", 0xB0006 ) + CmnDefLinkShell() : EventScript( 0xB0006 ) {} void Scene00001( Entity::Player& player ) diff --git a/scripts/native/CmnDef/HouFurOrchestrion.cpp b/scripts/native/CmnDef/HouFurOrchestrion.cpp index bb370e24..9e47c554 100644 --- a/scripts/native/CmnDef/HouFurOrchestrion.cpp +++ b/scripts/native/CmnDef/HouFurOrchestrion.cpp @@ -3,7 +3,7 @@ class HouFurOrchestrion : public EventScript { public: - HouFurOrchestrion() : EventScript( "HouFurOrchestrion", 721226 ) + HouFurOrchestrion() : EventScript( 721226 ) {} void Scene00000( Entity::Player& player ) diff --git a/scripts/native/action/ActionSprint3.cpp b/scripts/native/action/ActionSprint3.cpp index 6e9af153..076bbf5f 100644 --- a/scripts/native/action/ActionSprint3.cpp +++ b/scripts/native/action/ActionSprint3.cpp @@ -3,7 +3,7 @@ class ActionSprint3 : public ActionScript { public: - ActionSprint3() : ActionScript( "ActionSprint3", 3 ) + ActionSprint3() : ActionScript( 3 ) {} void onCastFinish( Core::Entity::Player& player, Core::Entity::Actor& targetActor ) override diff --git a/scripts/native/aetheryte/Aethernet.cpp b/scripts/native/aetheryte/Aethernet.cpp index b3881120..9a3ccd8f 100644 --- a/scripts/native/aetheryte/Aethernet.cpp +++ b/scripts/native/aetheryte/Aethernet.cpp @@ -12,7 +12,7 @@ class Aethernet : public EventScript { public: - Aethernet() : EventScript( "Aethernet", EVENTSCRIPT_AETHERNET_ID ) + Aethernet() : EventScript( EVENTSCRIPT_AETHERNET_ID ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override diff --git a/scripts/native/aetheryte/Aetheryte.cpp b/scripts/native/aetheryte/Aetheryte.cpp index 96ba8675..51ba6cb1 100644 --- a/scripts/native/aetheryte/Aetheryte.cpp +++ b/scripts/native/aetheryte/Aetheryte.cpp @@ -13,7 +13,7 @@ class Aetheryte : public EventScript { public: - Aetheryte() : EventScript( "Aetheryte", EVENTSCRIPT_AETHERYTE_ID ) + Aetheryte() : EventScript( EVENTSCRIPT_AETHERYTE_ID ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override diff --git a/scripts/native/opening/OpeningGridania.cpp b/scripts/native/opening/OpeningGridania.cpp index c6463ef7..9f6d6f0a 100644 --- a/scripts/native/opening/OpeningGridania.cpp +++ b/scripts/native/opening/OpeningGridania.cpp @@ -65,7 +65,7 @@ private: } public: - OpeningGridania() : EventScript( "OpeningGridania", 1245186 ) + OpeningGridania() : EventScript( 1245186 ) {} void onEnterZone( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override diff --git a/scripts/native/opening/OpeningLimsa.cpp b/scripts/native/opening/OpeningLimsa.cpp index 369e8686..a40ea482 100644 --- a/scripts/native/opening/OpeningLimsa.cpp +++ b/scripts/native/opening/OpeningLimsa.cpp @@ -81,7 +81,7 @@ private: public: - OpeningLimsa() : EventScript( "OpeningLimsa", 1245185 ) {} + OpeningLimsa() : EventScript( 1245185 ) {} void onEnterZone( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override { diff --git a/scripts/native/opening/OpeningUldah.cpp b/scripts/native/opening/OpeningUldah.cpp index ba940295..fdd1c5d2 100644 --- a/scripts/native/opening/OpeningUldah.cpp +++ b/scripts/native/opening/OpeningUldah.cpp @@ -65,7 +65,7 @@ private: public: - OpeningUldah() : EventScript( "OpeningUldah", 1245187 ) {} + OpeningUldah() : EventScript( 1245187 ) {} void onEnterZone( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override { diff --git a/scripts/native/quest/ManFst001.cpp b/scripts/native/quest/ManFst001.cpp index 726d2dc5..b73581ac 100644 --- a/scripts/native/quest/ManFst001.cpp +++ b/scripts/native/quest/ManFst001.cpp @@ -90,7 +90,7 @@ private: } public: - ManFst001() : EventScript( "ManFst001", 65575 ) {} + ManFst001() : EventScript( 65575 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/ManFst002.cpp b/scripts/native/quest/ManFst002.cpp index 6b084490..707150cb 100644 --- a/scripts/native/quest/ManFst002.cpp +++ b/scripts/native/quest/ManFst002.cpp @@ -189,7 +189,7 @@ private: } public: - ManFst002() : EventScript( "ManFst002", 65621 ) {} + ManFst002() : EventScript( 65621 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/ManFst003.cpp b/scripts/native/quest/ManFst003.cpp index e564a7ca..c8cd4da6 100644 --- a/scripts/native/quest/ManFst003.cpp +++ b/scripts/native/quest/ManFst003.cpp @@ -12,7 +12,7 @@ private: public: - ManFst003() : EventScript( "ManFst003", 65659 ) {} + ManFst003() : EventScript( 65659 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/ManFst004.cpp b/scripts/native/quest/ManFst004.cpp index b8896a41..18ac04b8 100644 --- a/scripts/native/quest/ManFst004.cpp +++ b/scripts/native/quest/ManFst004.cpp @@ -71,7 +71,7 @@ class ManFst004 : public EventScript static constexpr auto UnlockDesion = 14; public: - ManFst004() : EventScript( "Close to Home", 65660 ){}; + ManFst004() : EventScript( 65660 ){}; ~ManFst004(){}; ////////////////////////////////////////////////////////////////////// diff --git a/scripts/native/quest/ManSea001.cpp b/scripts/native/quest/ManSea001.cpp index 2a3e4aaa..aee4da80 100644 --- a/scripts/native/quest/ManSea001.cpp +++ b/scripts/native/quest/ManSea001.cpp @@ -145,7 +145,7 @@ private: } public: - ManSea001() : EventScript( "ManSea001", 65643 ) {} + ManSea001() : EventScript( 65643 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/ManSea002.cpp b/scripts/native/quest/ManSea002.cpp index 5db24e06..57d7dda7 100644 --- a/scripts/native/quest/ManSea002.cpp +++ b/scripts/native/quest/ManSea002.cpp @@ -136,7 +136,7 @@ private: player.eventPlay( getId(), 50, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, 0, 0, callback ); } public: - ManSea002() : EventScript( "ManSea002", 65644 ) {} + ManSea002() : EventScript( 65644 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/ManWil001.cpp b/scripts/native/quest/ManWil001.cpp index 93b7f42f..ee04e2aa 100644 --- a/scripts/native/quest/ManWil001.cpp +++ b/scripts/native/quest/ManWil001.cpp @@ -129,7 +129,7 @@ private: public: - ManWil001() : EventScript( "ManWil001", 66130 ) {} + ManWil001() : EventScript( 66130 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/ManWil002.cpp b/scripts/native/quest/ManWil002.cpp index 3f1c399c..9f160f72 100644 --- a/scripts/native/quest/ManWil002.cpp +++ b/scripts/native/quest/ManWil002.cpp @@ -144,7 +144,7 @@ private: public: - ManWil002() : EventScript( "ManWil002", 66104 ) { } + ManWil002() : EventScript( 66104 ) { } void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/subquest/gridania/SubFst001.cpp b/scripts/native/quest/subquest/gridania/SubFst001.cpp index c6b18dbc..2aedc7f8 100644 --- a/scripts/native/quest/subquest/gridania/SubFst001.cpp +++ b/scripts/native/quest/subquest/gridania/SubFst001.cpp @@ -60,7 +60,7 @@ private: public: - SubFst001() : EventScript( "SubFst001", 65560 ) {} + SubFst001() : EventScript( 65560 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/subquest/gridania/SubFst002.cpp b/scripts/native/quest/subquest/gridania/SubFst002.cpp index d128fe0f..2e32fa23 100644 --- a/scripts/native/quest/subquest/gridania/SubFst002.cpp +++ b/scripts/native/quest/subquest/gridania/SubFst002.cpp @@ -1,76 +1,76 @@ -#include "../../../ScriptObject.h" - -// Quest Script: SubFst002_00025 -// Quest Name: Quarrels with Squirrels -// Quest ID: 65561 -// Start NPC: 1000263 -// End NPC: 1000263 - -class SubFst002 : public EventScript -{ -private: - static constexpr auto SEQ_0 = 0; - static constexpr auto SEQ_1 = 1; - static constexpr auto SEQ_2 = 2; - static constexpr auto SEQ_FINISH = 255; - static constexpr auto ACTOR0 = 1000263; - static constexpr auto ENEMY0 = 37; - static constexpr auto SEQ_0_ACTOR0 = 0; - static constexpr auto SEQ_2_ACTOR0 = 1; - - void Scene00000( Entity::Player& player ) - { - auto callback = [&]( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2, uint16_t param3 ) - { - if( param2 == 1 ) // accept quest - { - player.updateQuest( getId(), SEQ_1 ); - } - }; - - player.eventPlay( getId (), 0, NONE, callback ); - } - - void Scene00001(Entity::Player& player) - { - auto callback = [&]( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2, uint16_t param3 ) - { - if( param2 == 1 ) // finish quest - { - if( player.giveQuestRewards( getId(), 0 ) ) - player.finishQuest( getId() ); - } - }; - - player.eventPlay( getId(), 1, NONE, callback ); - } - -public: - SubFst002() : EventScript( "SubFst002", 65561 ) {} - - void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override - { - auto actor = Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ); - - if( actor == ACTOR0 && !player.hasQuest( getId() ) ) - Scene00000( player ); - else if( actor == ACTOR0 && player.getQuestSeq( getId() ) == SEQ_FINISH ) - Scene00001( player ); - } - - void onNpcKill( uint32_t npcId, Entity::Player& player ) override - { - if( npcId != ENEMY0 ) - return; - - auto currentKC = player.getQuestUI8AL( getId() ) + 1; - - if( currentKC >= 6 ) - player.updateQuest( getId(), SEQ_FINISH ); - else - { - player.setQuestUI8AL( getId(), currentKC ); - player.sendQuestMessage( getId(), 0, 2, currentKC, 6 ); - } - } -}; +#include "../../../ScriptObject.h" + +// Quest Script: SubFst002_00025 +// Quest Name: Quarrels with Squirrels +// Quest ID: 65561 +// Start NPC: 1000263 +// End NPC: 1000263 + +class SubFst002 : public EventScript +{ +private: + static constexpr auto SEQ_0 = 0; + static constexpr auto SEQ_1 = 1; + static constexpr auto SEQ_2 = 2; + static constexpr auto SEQ_FINISH = 255; + static constexpr auto ACTOR0 = 1000263; + static constexpr auto ENEMY0 = 37; + static constexpr auto SEQ_0_ACTOR0 = 0; + static constexpr auto SEQ_2_ACTOR0 = 1; + + void Scene00000( Entity::Player& player ) + { + auto callback = [&]( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2, uint16_t param3 ) + { + if( param2 == 1 ) // accept quest + { + player.updateQuest( getId(), SEQ_1 ); + } + }; + + player.eventPlay( getId (), 0, NONE, callback ); + } + + void Scene00001(Entity::Player& player) + { + auto callback = [&]( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2, uint16_t param3 ) + { + if( param2 == 1 ) // finish quest + { + if( player.giveQuestRewards( getId(), 0 ) ) + player.finishQuest( getId() ); + } + }; + + player.eventPlay( getId(), 1, NONE, callback ); + } + +public: + SubFst002() : EventScript( 65561 ) {} + + void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override + { + auto actor = Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ); + + if( actor == ACTOR0 && !player.hasQuest( getId() ) ) + Scene00000( player ); + else if( actor == ACTOR0 && player.getQuestSeq( getId() ) == SEQ_FINISH ) + Scene00001( player ); + } + + void onNpcKill( uint32_t npcId, Entity::Player& player ) override + { + if( npcId != ENEMY0 ) + return; + + auto currentKC = player.getQuestUI8AL( getId() ) + 1; + + if( currentKC >= 6 ) + player.updateQuest( getId(), SEQ_FINISH ); + else + { + player.setQuestUI8AL( getId(), currentKC ); + player.sendQuestMessage( getId(), 0, 2, currentKC, 6 ); + } + } +}; diff --git a/scripts/native/quest/subquest/gridania/SubFst010.cpp b/scripts/native/quest/subquest/gridania/SubFst010.cpp index bccd887d..e3e03582 100644 --- a/scripts/native/quest/subquest/gridania/SubFst010.cpp +++ b/scripts/native/quest/subquest/gridania/SubFst010.cpp @@ -42,7 +42,7 @@ private: } public: - SubFst010() : EventScript( "SubFst010", 65537 ) {} + SubFst010() : EventScript( 65537 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/scripts/native/quest/subquest/gridania/SubFst013.cpp b/scripts/native/quest/subquest/gridania/SubFst013.cpp index d696642f..7bf4f6da 100644 --- a/scripts/native/quest/subquest/gridania/SubFst013.cpp +++ b/scripts/native/quest/subquest/gridania/SubFst013.cpp @@ -148,7 +148,7 @@ private: public: - SubFst013() : EventScript( "SubFst013", 65576 ) {} + SubFst013() : EventScript( 65576 ) {} void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 7d9fd527..606f027b 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -5,7 +5,8 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) file(GLOB UTILS_PUBLIC_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}/*.h") + "${CMAKE_CURRENT_SOURCE_DIR}/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Exd/*.h" ) file(GLOB UTILS_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Config/*.cpp" diff --git a/src/common/Common.h b/src/common/Common.h index 634c1828..94736d9b 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -162,29 +162,6 @@ namespace Common { instance, }; - enum TerritoryIntendedUseType : uint8_t //ToDo: Add The Rest of The Territory Types and Have Better Names For Them - { - Town = 0, - OpenWorld = 1, - Inn = 2, - Dungeon = 3, - JailArea = 5, - OpeningArea = 6, - BeforeTrialDung = 7, - AllianceRaid = 8, - OpenWorldInstanceBattle = 9, - Trial = 10, - HousingArea = 13, - HousingPrivateArea = 14, - MSQPrivateArea = 15, - Raids = 16, - RaidFights = 17, - ChocoboTutorial = 21, - Wedding = 22, - BeginnerTutorial = 27, - PalaceOfTheDead = 31, - }; - enum CharaLook : uint8_t { Race = 0x00, @@ -319,25 +296,6 @@ namespace Common { }; - enum EventType : uint16_t - { - Quest = 0x0001, - ChocoRent = 0x0002, - Shop = 0x0004, - Aetheryte = 0x0005, - GuildLeveAssign = 0x0006, - DefaultTalk = 0x0009, - CustomTalk = 0x000B, - CraftLeve = 0x000E, - ChocoPort = 0x0012, - Opening = 0x0013, - GCShop = 0x0016, - GuildOrderGuide = 0x0017, - GuildOrderOfficer = 0x0018, - Stories = 0x001A, - FcTalk = 0x001F, - }; - enum struct ActionAspect : uint8_t { None = 0, // Doesn't imply unaspected diff --git a/src/common/Database/DbConnection.cpp b/src/common/Database/DbConnection.cpp index b0633492..b33fbbd2 100644 --- a/src/common/Database/DbConnection.cpp +++ b/src/common/Database/DbConnection.cpp @@ -61,7 +61,7 @@ uint32_t Core::Db::DbConnection::open() try { m_pConnection = base->connect( m_connectionInfo.host, m_connectionInfo.user, m_connectionInfo.password, - options, m_connectionInfo.port ); + options, m_connectionInfo.port ); m_pConnection->setSchema( m_connectionInfo.database ); } @@ -79,9 +79,9 @@ uint32_t Core::Db::DbConnection::getLastError() return m_pConnection->getErrorNo(); } -void Core::Db::DbConnection::ping() +bool Core::Db::DbConnection::ping() { - m_pConnection->ping(); + return m_pConnection->ping(); } bool Core::Db::DbConnection::lockIfReady() @@ -146,6 +146,17 @@ boost::shared_ptr< Mysql::ResultSet > Core::Db::DbConnection::query( boost::shar if( !stmt ) return nullptr; + if( !ping() ) + { + g_log.error( "MysqlConnection went down" ); + // naivly reconnect and hope for the best + open(); + lockIfReady(); + if( !prepareStatements() ) + g_log.error( "Mysql Statements failed to prepare..." ); + g_log.info( "MysqlConnection reestablished" ); + } + uint32_t index = stmt->getIndex(); auto pStmt = getPreparedStatement( index ); diff --git a/src/common/Database/DbConnection.h b/src/common/Database/DbConnection.h index ddb66e17..f304e423 100644 --- a/src/common/Database/DbConnection.h +++ b/src/common/Database/DbConnection.h @@ -72,7 +72,7 @@ namespace Db void rollbackTransaction(); void commitTransaction(); - void ping(); + bool ping(); uint32_t getLastError(); bool lockIfReady(); diff --git a/src/common/Exd/ExdData.cpp b/src/common/Exd/ExdData.cpp index 9ac2197a..52b192af 100644 --- a/src/common/Exd/ExdData.cpp +++ b/src/common/Exd/ExdData.cpp @@ -85,10 +85,11 @@ bool Core::Data::ExdData::loadZoneInfo() int16_t map_index = getField< int16_t >( mapDataFields, 12 ); bool is_two_bytes = getField< bool >( mapDataFields, 15 ); - uint16_t weather_rate = getField< uint16_t >( fields, 10 ) > 75 ? 0 : getField< uint16_t >( fields, 10 ); + uint8_t weather_rate = getField< uint8_t >( fields, 12 ) > 75 ? 0 : getField< uint8_t >( fields, 12 ); auto weatherRateFields = weatherRate.get_row( weather_rate ); int32_t aetheryte_index = getField< int32_t >( fields, 23 ); + uint8_t zoneType = getField< uint8_t >( fields, 9 ); ZoneInfo info{ 0 }; @@ -101,6 +102,8 @@ bool Core::Data::ExdData::loadZoneInfo() info.map_id = map_id; info.weather_rate = weather_rate; // TODO: deal with weather groups info.aetheryte_index = aetheryte_index; + info.zone_type = zoneType; + uint8_t sumPc = 0; for( size_t i = 0; i < 16; ) diff --git a/src/common/Exd/ExdData.h b/src/common/Exd/ExdData.h index 3a5dedf9..d17bffb8 100644 --- a/src/common/Exd/ExdData.h +++ b/src/common/Exd/ExdData.h @@ -37,6 +37,7 @@ namespace Core { std::map< uint8_t, int32_t> weather_rate_map; int32_t aetheryte_index; + uint8_t zone_type; }; struct ClassJobInfo diff --git a/src/tools/exd_struct_test/ExdDataGenerated.cpp b/src/common/Exd/ExdDataGenerated.cpp similarity index 99% rename from src/tools/exd_struct_test/ExdDataGenerated.cpp rename to src/common/Exd/ExdDataGenerated.cpp index f8d711b8..ff6e1a45 100644 --- a/src/tools/exd_struct_test/ExdDataGenerated.cpp +++ b/src/common/Exd/ExdDataGenerated.cpp @@ -3532,6 +3532,7 @@ placeNameZone = exdData->getField< uint16_t >( row, 4 ); placeName = exdData->getField< uint16_t >( row, 5 ); map = exdData->getField< uint16_t >( row, 6 ); + territoryIntendedUse = exdData->getField< uint8_t >( row, 9 ); weatherRate = exdData->getField< uint8_t >( row, 12 ); aetheryte = exdData->getField< int32_t >( row, 23 ); } diff --git a/src/tools/exd_struct_test/ExdDataGenerated.h b/src/common/Exd/ExdDataGenerated.h similarity index 99% rename from src/tools/exd_struct_test/ExdDataGenerated.h rename to src/common/Exd/ExdDataGenerated.h index 24b1149d..530caaf0 100644 --- a/src/tools/exd_struct_test/ExdDataGenerated.h +++ b/src/common/Exd/ExdDataGenerated.h @@ -1,5 +1,5 @@ -#ifndef _EXDDATA_H -#define _EXDDATA_H +#ifndef _EXDDATAGENERATED_H +#define _EXDDATAGENERATED_H /* This file has been automatically generated. Changes will be lost upon regeneration. @@ -3020,12 +3020,12 @@ struct TerritoryType uint16_t placeNameZone; uint16_t placeName; uint16_t map; + uint8_t territoryIntendedUse; uint8_t weatherRate; int32_t aetheryte; TerritoryType( uint32_t row_id, Core::Data::ExdDataGenerated* exdData ); }; - struct TextCommand { std::string command; diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index dcbe9114..4022cdf4 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -365,7 +365,7 @@ struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket uint32_t bNPCName; uint32_t u18; uint32_t u19; - uint32_t u20; + uint32_t directorId; uint32_t ownerId; uint32_t u22; uint32_t hPMax; diff --git a/src/libraries b/src/libraries index f4d3c5b3..978d3d2a 160000 --- a/src/libraries +++ b/src/libraries @@ -1 +1 @@ -Subproject commit f4d3c5b38d13a15efc42686c9bac768c2be28be1 +Subproject commit 978d3d2a336b97bb6ea0d95dc7000cbc1618a8cc diff --git a/src/servers/sapphire_api/Forwards.h b/src/servers/sapphire_api/Forwards.h index 56d3b92d..bdffff9f 100644 --- a/src/servers/sapphire_api/Forwards.h +++ b/src/servers/sapphire_api/Forwards.h @@ -45,9 +45,9 @@ namespace Core namespace Event { - class Event; + class EventHandler; - typedef boost::shared_ptr EventPtr; + typedef boost::shared_ptr EventPtr; } namespace Action diff --git a/src/servers/sapphire_zone/Action/ActionCast.cpp b/src/servers/sapphire_zone/Action/ActionCast.cpp index 002504fd..b9289b30 100644 --- a/src/servers/sapphire_zone/Action/ActionCast.cpp +++ b/src/servers/sapphire_zone/Action/ActionCast.cpp @@ -58,7 +58,6 @@ void Core::Action::ActionCast::onStart() m_pSource->sendToInRangeSet( castPacket, true ); m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); } @@ -71,7 +70,6 @@ void Core::Action::ActionCast::onFinish() pPlayer->sendDebug( "onFinish()" ); pPlayer->unsetStateFlag( PlayerStateFlag::Casting ); - pPlayer->sendStateFlags(); /*auto control = ActorControlPacket143( m_pTarget->getId(), ActorControlType::Unk7, 0x219, m_id, m_id, m_id, m_id ); @@ -87,7 +85,6 @@ void Core::Action::ActionCast::onInterrupt() m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, 0x219, 1, m_id, 0 ); diff --git a/src/servers/sapphire_zone/Action/ActionMount.cpp b/src/servers/sapphire_zone/Action/ActionMount.cpp index 6ff6c8b9..5e5a4846 100644 --- a/src/servers/sapphire_zone/Action/ActionMount.cpp +++ b/src/servers/sapphire_zone/Action/ActionMount.cpp @@ -60,7 +60,6 @@ void Core::Action::ActionMount::onStart() m_pSource->sendToInRangeSet( castPacket, true ); m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); } @@ -73,7 +72,6 @@ void Core::Action::ActionMount::onFinish() pPlayer->sendDebug( "ActionMount::onFinish()" ); pPlayer->unsetStateFlag( PlayerStateFlag::Casting ); - pPlayer->sendStateFlags(); ZoneChannelPacket< FFXIVIpcEffect > effectPacket( pPlayer->getId() ); effectPacket.data().targetId = pPlayer->getId(); @@ -100,7 +98,6 @@ void Core::Action::ActionMount::onInterrupt() m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, 0x219, 1, m_id, 0 ); diff --git a/src/servers/sapphire_zone/Action/ActionTeleport.cpp b/src/servers/sapphire_zone/Action/ActionTeleport.cpp index 7e8cec18..bb53e522 100644 --- a/src/servers/sapphire_zone/Action/ActionTeleport.cpp +++ b/src/servers/sapphire_zone/Action/ActionTeleport.cpp @@ -54,7 +54,6 @@ void Core::Action::ActionTeleport::onStart() m_pSource->sendToInRangeSet( castPacket, true ); m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); } @@ -75,7 +74,6 @@ void Core::Action::ActionTeleport::onFinish() pPlayer->removeCurrency( Inventory::CurrencyType::Gil, m_cost ); pPlayer->unsetStateFlag( PlayerStateFlag::Casting ); - pPlayer->sendStateFlags(); // TODO: not sure if this ever gets sent //auto control = Network::Packets::Server::ActorControlPacket142( m_pSource->getId(), Common::ActorControlType::TeleportDone ); @@ -105,7 +103,6 @@ void Core::Action::ActionTeleport::onInterrupt() return; m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, 0x219, 0x04, m_id, 0 ); diff --git a/src/servers/sapphire_zone/Action/EventAction.cpp b/src/servers/sapphire_zone/Action/EventAction.cpp index b174bdad..869fa089 100644 --- a/src/servers/sapphire_zone/Action/EventAction.cpp +++ b/src/servers/sapphire_zone/Action/EventAction.cpp @@ -6,7 +6,7 @@ #include "Network/PacketWrappers/ActorControlPacket142.h" #include "Network/PacketWrappers/ActorControlPacket143.h" #include "Actor/Player.h" -#include "Event/Event.h" +#include "Event/EventHandler.h" extern Core::Logger g_log; extern Core::Data::ExdData g_exdData; @@ -54,7 +54,6 @@ void Core::Action::EventAction::onStart() { m_pSource->sendToInRangeSet( control, true ); m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::SomeFlag ); - m_pSource->getAsPlayer()->sendStateFlags(); } else m_pSource->sendToInRangeSet( control ); @@ -84,7 +83,6 @@ void Core::Action::EventAction::onFinish() if( m_pSource->isPlayer() ) { m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::SomeFlag ); - m_pSource->getAsPlayer()->sendStateFlags(); m_pSource->sendToInRangeSet( control, true ); } else @@ -114,7 +112,6 @@ void Core::Action::EventAction::onInterrupt() m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::NoCombat ); m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); - m_pSource->getAsPlayer()->sendStateFlags(); m_pSource->sendToInRangeSet( control ); m_pSource->sendToInRangeSet( control1 ); diff --git a/src/servers/sapphire_zone/Action/EventItemAction.cpp b/src/servers/sapphire_zone/Action/EventItemAction.cpp index 3a8c3f78..28ddd8fb 100644 --- a/src/servers/sapphire_zone/Action/EventItemAction.cpp +++ b/src/servers/sapphire_zone/Action/EventItemAction.cpp @@ -56,7 +56,6 @@ void Core::Action::EventItemAction::onStart() m_pSource->sendToInRangeSet( castPacket, true ); m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); } @@ -78,7 +77,6 @@ void Core::Action::EventItemAction::onFinish() effectPacket.data().effectTarget = static_cast< uint32_t >( m_additional ); m_pSource->getAsPlayer()->unsetStateFlag( Common::PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); m_pSource->sendToInRangeSet( effectPacket, true ); if( m_onActionFinishClb ) @@ -104,7 +102,6 @@ void Core::Action::EventItemAction::onInterrupt() if( m_pSource->isPlayer() ) { m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting ); - m_pSource->getAsPlayer()->sendStateFlags(); m_pSource->sendToInRangeSet( control, true ); } else diff --git a/src/servers/sapphire_zone/Actor/Actor.h b/src/servers/sapphire_zone/Actor/Actor.h index 9ceffb55..08ff963b 100644 --- a/src/servers/sapphire_zone/Actor/Actor.h +++ b/src/servers/sapphire_zone/Actor/Actor.h @@ -16,7 +16,6 @@ namespace Entity { \class Actor \brief Base class for all actors -\author Mordred */ class Actor : public boost::enable_shared_from_this< Actor > { diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 6365098b..fa8c1d3b 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -11,7 +11,7 @@ #include "Player.h" #include "BattleNpc.h" -#include "Zone/ZoneMgr.h" +#include "Zone/TerritoryMgr.h" #include "Zone/Zone.h" #include "ServerZone.h" @@ -32,7 +32,7 @@ #include "Inventory/Item.h" #include "Inventory/Inventory.h" -#include "Event/Event.h" +#include "Event/EventHandler.h" #include "Action/Action.h" #include "Action/EventAction.h" #include "Action/EventItemAction.h" @@ -43,7 +43,7 @@ extern Core::Logger g_log; extern Core::ServerZone g_serverZone; -extern Core::ZoneMgr g_zoneMgr; +extern Core::TerritoryMgr g_territoryMgr; extern Core::Data::ExdData g_exdData; extern Core::Scripting::ScriptManager g_scriptMgr; @@ -308,9 +308,8 @@ void Core::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type ) } setStateFlag( PlayerStateFlag::BetweenAreas ); - sendStateFlags(); - auto z_pos = g_zoneMgr.getZonePosition( data->levelId ); + auto z_pos = g_territoryMgr.getTerritoryPosition( data->levelId ); Common::FFXIVARR_POSITION3 pos; pos.x = 0; @@ -366,101 +365,62 @@ void Core::Entity::Player::returnToHomepoint() void Core::Entity::Player::setZone( uint32_t zoneId ) { - auto pPlayer = getAsPlayer(); - - auto pZone = g_zoneMgr.getZone( zoneId ); - - - if( !pZone /*|| ( ( pZone == m_pCurrentZone ) && m_lastPing )*/ ) + if( !g_territoryMgr.movePlayer( zoneId, getAsPlayer() ) ) { - g_log.error( "Zone " + std::to_string( zoneId ) + " not found on this server." ); - return; + // todo: this will require proper handling, for now just return the player to their previous area + m_pos = m_prevPos; + m_rot = m_prevRot; + m_zoneId = m_prevZoneId; + + if( !g_territoryMgr.movePlayer( m_zoneId, getAsPlayer() ) ) + return; } - m_zoneId = zoneId; + sendZonePackets(); +} - // mark character as zoning in progress - setLoadingComplete( false ); +bool Core::Entity::Player::setInstance( uint32_t instanceContentId ) +{ + auto instance = g_territoryMgr.getInstanceZonePtr( instanceContentId ); + if( !instance ) + return false; - if( m_lastPing != 0 ) - m_pCurrentZone->removeActor( shared_from_this() ); + return setInstance( instance ); +} - m_pCurrentZone = pZone; - m_pCurrentZone->pushActor( shared_from_this() ); +bool Core::Entity::Player::setInstance( ZonePtr instance ) +{ + if( !instance ) + return false; - ZoneChannelPacket< FFXIVIpcInit > initPacket( getId() ); - initPacket.data().charId = getId(); - queuePacket( initPacket ); - - sendInventory(); - - if( isLogin() ) + // zoning within the same zone won't cause the prev data to be overwritten + if( instance->getTerritoryId() != m_zoneId ) { - queuePacket(ActorControlPacket143( getId(), SetCharaGearParamUI, m_equipDisplayFlags, 1 ) ); + m_prevPos = m_pos; + m_prevRot = m_rot; + m_prevZoneId = m_zoneId; } - // set flags, will be reset automatically by zoning ( only on client side though ) - pPlayer->setStateFlag( PlayerStateFlag::BetweenAreas ); - pPlayer->setStateFlag( PlayerStateFlag::BetweenAreas1 ); - pPlayer->sendStateFlags(); + if( !g_territoryMgr.movePlayer( instance, getAsPlayer() ) ) + return false; - pPlayer->sendStats(); + sendZonePackets(); - // only initialize the UI if the player in fact just logged in. - if( isLogin() ) - { - ZoneChannelPacket< FFXIVIpcCFAvailableContents > contentFinderList( getId() ); - for( auto i = 0; i < sizeof( contentFinderList.data().contents ); i++ ) - { - // unlock all contents for now - contentFinderList.data().contents[i] = 0xFF; - } - queuePacket( contentFinderList ); + return true; +} - Server::InitUIPacket initUIPacket( *pPlayer ); - queuePacket( initUIPacket ); +bool Core::Entity::Player::exitInstance() +{ + if( !g_territoryMgr.movePlayer( m_prevZoneId, getAsPlayer() ) ) + return false; - ZoneChannelPacket< FFXIVIpcPlayerClassInfo > classInfoPacket( getId() ); - classInfoPacket.data().classId = static_cast< uint8_t >( getClass() ); - classInfoPacket.data().unknown = 1; - classInfoPacket.data().level = getLevel(); - classInfoPacket.data().level1 = getLevel(); - queuePacket( classInfoPacket ); + m_pos = m_prevPos; + m_rot = m_prevRot; + m_zoneId = m_prevZoneId; - ZoneChannelPacket< FFXIVGCAffiliation > gcAffPacket( getId() ); - gcAffPacket.data().gcId = m_gc; - gcAffPacket.data().gcRank[0] = m_gcRank[0]; - gcAffPacket.data().gcRank[1] = m_gcRank[1]; - gcAffPacket.data().gcRank[2] = m_gcRank[2]; - queuePacket( gcAffPacket ); + sendZonePackets(); - m_itemLevel = getInventory()->calculateEquippedGearItemLevel(); - sendItemLevel(); - } - - ZoneChannelPacket< FFXIVIpcInitZone > initZonePacket( getId() ); - initZonePacket.data().zoneId = getCurrentZone()->getLayoutId(); - initZonePacket.data().weatherId = static_cast< uint8_t >( getCurrentZone()->getCurrentWeather() ); - initZonePacket.data().bitmask = 0x1; - initZonePacket.data().unknown5 = 0x2A; - initZonePacket.data().pos.x = getPos().x; - initZonePacket.data().pos.y = getPos().y; - initZonePacket.data().pos.z = getPos().z; - queuePacket( initZonePacket ); - - if( isLogin() ) - { - ZoneChannelPacket< FFXIVARR_IPC_UNK322 > unk322( getId() ); - queuePacket( unk322 ); - - ZoneChannelPacket< FFXIVARR_IPC_UNK320 > unk320( getId() ); - queuePacket( unk320 ); - } - - if( getLastPing() == 0 ) - sendQuestInfo(); - - m_bMarkedForZoning = false; + return true; } uint32_t Core::Entity::Player::getPlayTime() const @@ -542,7 +502,7 @@ void Core::Entity::Player::discover( int16_t map_id, int16_t sub_id ) int32_t offset = 4; - auto info = g_exdData.m_zoneInfoMap[getCurrentZone()->getId()]; + auto info = g_exdData.m_zoneInfoMap[getCurrentZone()->getTerritoryId()]; if( info.is_two_byte ) offset = 4 + 2 * info.discovery_index; else @@ -580,7 +540,6 @@ void Core::Entity::Player::setNewAdventurer( bool state ) //{ // setStateFlag( PlayerStateFlag::NewAdventurer ); //} - sendStateFlags(); m_bNewAdventurer = state; } @@ -972,6 +931,7 @@ bool Core::Entity::Player::hasStateFlag( Common::PlayerStateFlag flag ) const void Core::Entity::Player::setStateFlag( Common::PlayerStateFlag flag ) { + auto prevOnlineStatus = getOnlineStatus(); int32_t iFlag = static_cast< uint32_t >( flag ); uint16_t index; @@ -979,6 +939,13 @@ void Core::Entity::Player::setStateFlag( Common::PlayerStateFlag flag ) Util::valueToFlagByteIndexValue( iFlag, value, index ); m_stateFlags[index] |= value; + sendStateFlags(); + + auto newOnlineStatus = getOnlineStatus(); + + if( prevOnlineStatus != newOnlineStatus ) + sendToInRangeSet( ActorControlPacket142( getId(), SetStatusIcon, + static_cast< uint8_t >( getOnlineStatus() ) ), true ); } @@ -986,13 +953,7 @@ void Core::Entity::Player::setStateFlags( std::vector< Common::PlayerStateFlag > { for( const auto& flag : flags ) { - int iFlag = static_cast< uint32_t >( flag ); - - uint16_t index; - uint8_t value; - Util::valueToFlagByteIndexValue( iFlag, value, index ); - - m_stateFlags[index] |= value; + setStateFlag( flag ); } } @@ -1006,6 +967,8 @@ void Core::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag ) if( !hasStateFlag( flag ) ) return; + auto prevOnlineStatus = getOnlineStatus(); + int32_t iFlag = static_cast< uint32_t >( flag ); uint16_t index; @@ -1013,7 +976,13 @@ void Core::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag ) Util::valueToFlagByteIndexValue( iFlag, value, index ); m_stateFlags[index] ^= value; + sendStateFlags(); + auto newOnlineStatus = getOnlineStatus(); + + if( prevOnlineStatus != newOnlineStatus ) + sendToInRangeSet( ActorControlPacket142( getId(), SetStatusIcon, + static_cast< uint8_t >( getOnlineStatus() ) ), true ); } void Core::Entity::Player::update( int64_t currTime ) @@ -1023,7 +992,7 @@ void Core::Entity::Player::update( int64_t currTime ) if( m_queuedZoneing && ( currTime - m_queuedZoneing->m_queueTime ) > 800 ) { Common::FFXIVARR_POSITION3 targetPos = m_queuedZoneing->m_targetPosition; - if( getCurrentZone()->getId() != m_queuedZoneing->m_targetZone ) + if( getCurrentZone()->getTerritoryId() != m_queuedZoneing->m_targetZone ) { performZoning( m_queuedZoneing->m_targetZone, targetPos, m_queuedZoneing->m_targetRotation); } @@ -1596,3 +1565,89 @@ void Core::Entity::Player::setEorzeaTimeOffset( uint64_t timestamp ) // Send to single player queuePacket( packet ); } + +void Player::setTerritoryId( uint32_t territoryId ) +{ + m_zoneId = territoryId; +} + +uint32_t Player::getTerritoryId() const +{ + return m_zoneId; +} + +void Player::sendZonePackets() +{ + ZoneChannelPacket< FFXIVIpcInit > initPacket( getId() ); + initPacket.data().charId = getId(); + queuePacket( initPacket ); + + sendInventory(); + + if( isLogin() ) + { + queuePacket(ActorControlPacket143( getId(), SetCharaGearParamUI, m_equipDisplayFlags, 1 ) ); + } + + // set flags, will be reset automatically by zoning ( only on client side though ) + setStateFlag( PlayerStateFlag::BetweenAreas ); + setStateFlag( PlayerStateFlag::BetweenAreas1 ); + + sendStats(); + + // only initialize the UI if the player in fact just logged in. + if( isLogin() ) + { + ZoneChannelPacket< FFXIVIpcCFAvailableContents > contentFinderList( getId() ); + for( auto i = 0; i < sizeof( contentFinderList.data().contents ); i++ ) + { + // unlock all contents for now + contentFinderList.data().contents[i] = 0xFF; + } + queuePacket( contentFinderList ); + + Server::InitUIPacket initUIPacket( *this ); + queuePacket( initUIPacket ); + + ZoneChannelPacket< FFXIVIpcPlayerClassInfo > classInfoPacket( getId() ); + classInfoPacket.data().classId = static_cast< uint8_t >( getClass() ); + classInfoPacket.data().unknown = 1; + classInfoPacket.data().level = getLevel(); + classInfoPacket.data().level1 = getLevel(); + queuePacket( classInfoPacket ); + + ZoneChannelPacket< FFXIVGCAffiliation > gcAffPacket( getId() ); + gcAffPacket.data().gcId = m_gc; + gcAffPacket.data().gcRank[0] = m_gcRank[0]; + gcAffPacket.data().gcRank[1] = m_gcRank[1]; + gcAffPacket.data().gcRank[2] = m_gcRank[2]; + queuePacket( gcAffPacket ); + + m_itemLevel = getInventory()->calculateEquippedGearItemLevel(); + sendItemLevel(); + } + + ZoneChannelPacket< FFXIVIpcInitZone > initZonePacket( getId() ); + initZonePacket.data().zoneId = getCurrentZone()->getTerritoryId(); + initZonePacket.data().weatherId = static_cast< uint8_t >( getCurrentZone()->getCurrentWeather() ); + initZonePacket.data().bitmask = 0x1; + initZonePacket.data().unknown5 = 0x2A; + initZonePacket.data().pos.x = getPos().x; + initZonePacket.data().pos.y = getPos().y; + initZonePacket.data().pos.z = getPos().z; + queuePacket( initZonePacket ); + + if( isLogin() ) + { + ZoneChannelPacket< FFXIVARR_IPC_UNK322 > unk322( getId() ); + queuePacket( unk322 ); + + ZoneChannelPacket< FFXIVARR_IPC_UNK320 > unk320( getId() ); + queuePacket( unk320 ); + } + + if( getLastPing() == 0 ) + sendQuestInfo(); + + m_bMarkedForZoning = false; +} diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index ea7b7027..3bb6f9e5 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -7,6 +7,7 @@ #include "Actor.h" #include "Inventory/Inventory.h" +#include "Event/EventHandler.h" #include #include @@ -50,31 +51,33 @@ public: /*! start an event item action */ void eventItemActionStart( uint32_t eventId, uint32_t action, ActionCallback finishCallback, ActionCallback interruptCallback, uint64_t additional ); /*! start/register a normal event */ - void eventStart( uint64_t actorId, uint32_t eventId, uint8_t eventParam, uint8_t eventParam1, uint32_t eventParam2 ); + void eventStart( uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventParam, uint8_t eventParam1, uint32_t eventParam2 ); /*! play a subevent */ void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t eventParam2, uint32_t eventParam3 ); /*! play a subevent */ void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, - uint32_t eventParam2, uint32_t eventParam3, Scripting::EventReturnCallback eventReturnCallback ); + uint32_t eventParam2, uint32_t eventParam3, Event::EventHandler::SceneReturnCallback eventReturnCallback ); /*! play a subevent */ void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, - uint32_t eventParam2, uint32_t eventParam3, uint32_t eventParam4, Scripting::EventReturnCallback eventReturnCallback ); + uint32_t eventParam2, uint32_t eventParam3, uint32_t eventParam4, + Event::EventHandler::SceneReturnCallback eventReturnCallback ); /*! play a subevent */ - void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, Scripting::EventReturnCallback eventReturnCallback ); + void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, + Event::EventHandler::SceneReturnCallback eventReturnCallback ); /*! play a subevent */ void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags ); /*! finish / unregister an event */ void eventFinish( uint32_t eventId, uint32_t freePlayer ); /*! add an event to the event array */ - void addEvent( Event::EventPtr pEvent ); + void addEvent( Event::EventHandlerPtr pEvent ); /*! retrieve an event from the event array */ - Event::EventPtr getEvent( uint32_t eventId ); + Event::EventHandlerPtr getEvent( uint32_t eventId ); /*! get number of active events */ size_t getEventCount(); /*! remove an event from the event array */ void removeEvent( uint32_t eventId ); /*! return the eventlist */ - std::map< uint32_t, Event::EventPtr >& eventList(); + std::map< uint32_t, Event::EventHandlerPtr >& eventList(); void checkEvent( uint32_t eventId ); @@ -306,6 +309,16 @@ public: Common::OnlineStatus getOnlineStatus(); /*! sets the players zone, initiating a zoning process */ void setZone( uint32_t zoneId ); + /*! sets the players instance & initiates zoning process */ + bool setInstance( uint32_t instanceContentId ); + /*! sets the players instance & initiates zoning process */ + bool setInstance( ZonePtr instance ); + /*! returns the player to their position before zoning into an instance */ + bool exitInstance(); + /*! sets the players territoryId */ + void setTerritoryId( uint32_t territoryId ); + /*! gets the players territoryId */ + uint32_t getTerritoryId() const; void forceZoneing( uint32_t zoneId ); /*! return player to preset homepoint */ @@ -468,10 +481,12 @@ public: /*! set the loading complete bool */ void setLoadingComplete( bool bComplete ); /*! mark this player for zoning, notify worldserver */ - void performZoning(uint16_t zoneId, const Common::FFXIVARR_POSITION3& pos, float rotation); + void performZoning( uint16_t zoneId, const Common::FFXIVARR_POSITION3& pos, float rotation ); /*! return true if the player is marked for zoning */ bool isMarkedForZoning() const; + void sendZonePackets(); + Common::ZoneingType getZoningType() const; void setZoningType( Common::ZoneingType zoneingType ); @@ -553,6 +568,11 @@ private: private: + Common::FFXIVARR_POSITION3 m_prevPos; + uint32_t m_prevZoneType; + uint32_t m_prevZoneId; + float m_prevRot; + uint8_t m_voice; uint64_t m_modelMainWeapon; @@ -600,7 +620,8 @@ private: uint16_t m_itemLevel; InventoryPtr m_pInventory; - std::map< uint32_t, Event::EventPtr > m_eventMap; + std::map< uint32_t, Event::EventHandlerPtr > m_eventHandlerMap; + std::map< uint32_t, uint8_t > m_playerIdToSpawnIdMap; // maps player to spawn id std::queue< uint8_t > m_freeSpawnIdQueue; // queue with spawn ids free to be assigned std::queue< uint8_t > m_freeHateSlotQueue; // queue with "hate slots" free to be assigned diff --git a/src/servers/sapphire_zone/Actor/PlayerEvent.cpp b/src/servers/sapphire_zone/Actor/PlayerEvent.cpp index a48aea17..2e08bdb4 100644 --- a/src/servers/sapphire_zone/Actor/PlayerEvent.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerEvent.cpp @@ -21,8 +21,8 @@ #include "Action/EventAction.h" #include "Action/EventItemAction.h" -#include "Event/Event.h" -#include "Event/Event.h" +#include "Event/EventHandler.h" +#include "Event/EventHandler.h" #include "ServerZone.h" extern Core::Logger g_log; @@ -32,37 +32,37 @@ using namespace Core::Common; using namespace Core::Network::Packets; using namespace Core::Network::Packets::Server; -void Core::Entity::Player::addEvent( Event::EventPtr pEvent ) +void Core::Entity::Player::addEvent( Event::EventHandlerPtr pEvent ) { - m_eventMap[pEvent->getId()] = pEvent; + m_eventHandlerMap[pEvent->getId()] = pEvent; } -std::map< uint32_t, Core::Event::EventPtr >& Core::Entity::Player::eventList() +std::map< uint32_t, Core::Event::EventHandlerPtr >& Core::Entity::Player::eventList() { - return m_eventMap; + return m_eventHandlerMap; } -Core::Event::EventPtr Core::Entity::Player::getEvent( uint32_t eventId ) +Core::Event::EventHandlerPtr Core::Entity::Player::getEvent( uint32_t eventId ) { - auto it = m_eventMap.find( eventId ); - if( it != m_eventMap.end() ) + auto it = m_eventHandlerMap.find( eventId ); + if( it != m_eventHandlerMap.end() ) return it->second; - return Event::EventPtr( nullptr ); + return Event::EventHandlerPtr( nullptr ); } size_t Core::Entity::Player::getEventCount() { - return m_eventMap.size(); + return m_eventHandlerMap.size(); } void Core::Entity::Player::removeEvent( uint32_t eventId ) { - auto it = m_eventMap.find( eventId ); - if( it != m_eventMap.end() ) + auto it = m_eventHandlerMap.find( eventId ); + if( it != m_eventHandlerMap.end() ) { auto tmpEvent = it->second; - m_eventMap.erase( it ); + m_eventHandlerMap.erase( it ); } } @@ -76,14 +76,15 @@ void Core::Entity::Player::checkEvent( uint32_t eventId ) void Core::Entity::Player::eventStart( uint64_t actorId, uint32_t eventId, - uint8_t eventType, uint8_t eventParam1, + Event::EventHandler::EventType eventType, uint8_t eventParam1, uint32_t eventParam2 ) { - Event::EventPtr newEvent( new Event::Event( actorId, eventId, eventType, eventParam1, eventParam2 ) ); + + Event::EventHandlerPtr newEvent( new Event::EventHandler( this, actorId, eventId, eventType, eventParam2 ) ); + addEvent( newEvent ); setStateFlag( PlayerStateFlag::Occupied2 ); - sendStateFlags(); EventStartPacket eventStart( getId(), actorId, eventId, eventType, eventParam1, eventParam2 ); @@ -99,7 +100,7 @@ void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, } void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, - uint32_t flags, Scripting::EventReturnCallback eventCallback ) + uint32_t flags, Event::EventHandler::SceneReturnCallback eventCallback ) { eventPlay( eventId, scene, flags, 0, 0, eventCallback ); } @@ -111,20 +112,16 @@ void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, uint32_t void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t eventParam2, - uint32_t eventParam3, Scripting::EventReturnCallback eventCallback ) + uint32_t eventParam3, Event::EventHandler::SceneReturnCallback eventCallback ) { if( flags & 0x02 ) - { setStateFlag( PlayerStateFlag::WatchingCutscene ); - sendToInRangeSet( ActorControlPacket142( getId(), SetStatusIcon, - static_cast< uint8_t >( getOnlineStatus() ) ), true ); - } auto pEvent = getEvent( eventId ); if( !pEvent && getEventCount() ) { // We're trying to play a nested event, need to start it first. - eventStart( getId(), eventId, Event::Event::Nest, 0, 0 ); + eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 ); pEvent = getEvent( eventId ); } else if( !pEvent ) @@ -143,20 +140,16 @@ void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, void Core::Entity::Player::eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t eventParam2, - uint32_t eventParam3, uint32_t eventParam4, Scripting::EventReturnCallback eventCallback ) + uint32_t eventParam3, uint32_t eventParam4, Event::EventHandler::SceneReturnCallback eventCallback ) { if( flags & 0x02 ) - { setStateFlag( PlayerStateFlag::WatchingCutscene ); - sendToInRangeSet( ActorControlPacket142( getId(), SetStatusIcon, - static_cast< uint8_t >( getOnlineStatus() ) ), true ); - } auto pEvent = getEvent( eventId ); if( !pEvent && getEventCount() ) { // We're trying to play a nested event, need to start it first. - eventStart( getId(), eventId, Event::Event::Nest, 0, 0 ); + eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 ); pEvent = getEvent( eventId ); } else if( !pEvent ) @@ -183,7 +176,7 @@ void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer ) return; } - if( getEventCount() > 1 && pEvent->getEventType() != Event::Event::Nest ) + if( getEventCount() > 1 && pEvent->getEventType() != Event::EventHandler::Nest ) { // this is the parent of a nested event, we can't finish it until the parent finishes return; @@ -191,9 +184,9 @@ void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer ) switch( pEvent->getEventType() ) { - case Event::Event::Nest: + case Event::EventHandler::Nest: { - queuePacket( EventFinishPacket( getId(), pEvent->getId(), pEvent->getEventType(), pEvent->getEventParam3() ) ); + queuePacket( EventFinishPacket( getId(), pEvent->getId(), pEvent->getEventType(), pEvent->getEventParam() ) ); removeEvent( pEvent->getId() ); auto events = eventList(); @@ -204,7 +197,8 @@ void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer ) if( it.second->hasPlayedScene() == false ) { // TODO: not happy with this, this is also prone to break wit more than one remaining event in there - queuePacket( EventFinishPacket( getId(), it.second->getId(), it.second->getEventType(), it.second->getEventParam3() ) ); + queuePacket( EventFinishPacket( getId(), it.second->getId(), it.second->getEventType(), + it.second->getEventParam() ) ); removeEvent( it.second->getId() ); } } @@ -213,25 +207,18 @@ void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer ) } default: { - queuePacket( EventFinishPacket( getId(), pEvent->getId(), pEvent->getEventType(), pEvent->getEventParam3() ) ); + queuePacket( EventFinishPacket( getId(), pEvent->getId(), pEvent->getEventType(), pEvent->getEventParam() ) ); break; } } if( hasStateFlag( PlayerStateFlag::WatchingCutscene ) ) - { unsetStateFlag( PlayerStateFlag::WatchingCutscene ); - sendToInRangeSet( ActorControlPacket142( getId(), SetStatusIcon, - static_cast< uint8_t >( getOnlineStatus() ) ), true ); - } removeEvent( pEvent->getId() ); if( freePlayer == 1 ) - { unsetStateFlag( PlayerStateFlag::Occupied2 ); - sendStateFlags(); - } } void Core::Entity::Player::eventActionStart( uint32_t eventId, @@ -249,7 +236,7 @@ void Core::Entity::Player::eventActionStart( uint32_t eventId, if( !pEvent && getEventCount() ) { // We're trying to play a nested event, need to start it first. - eventStart( getId(), eventId, Event::Event::Nest, 0, 0 ); + eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 ); pEvent = getEvent( eventId ); } else if( !pEvent ) diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index 6e201984..e20dfa88 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -5,7 +5,6 @@ #include "Player.h" -#include "Zone/ZoneMgr.h" #include "Zone/Zone.h" #include "Network/PacketWrappers/ActorControlPacket142.h" diff --git a/src/servers/sapphire_zone/Actor/PlayerSql.cpp b/src/servers/sapphire_zone/Actor/PlayerSql.cpp index 5a242c52..044dd5ea 100644 --- a/src/servers/sapphire_zone/Actor/PlayerSql.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerSql.cpp @@ -16,7 +16,7 @@ #include "Player.h" -#include "Zone/ZoneMgr.h" +#include "Zone/TerritoryMgr.h" #include "Zone/Zone.h" #include "ServerZone.h" @@ -30,7 +30,7 @@ extern Core::Logger g_log; extern Core::ServerZone g_serverZone; -extern Core::ZoneMgr g_zoneMgr; +extern Core::TerritoryMgr g_territoryMgr; extern Core::Data::ExdData g_exdData; @@ -47,7 +47,7 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) stmt->setUInt( 1, charId ); auto res = g_charaDb.query( stmt ); - + if( !res->next() ) return false; @@ -57,8 +57,10 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) strcpy( m_name, name.c_str() ); auto zoneId = res->getUInt( "TerritoryId" ); + m_prevZoneId = res->getUInt( "OTerritoryId" ); + m_prevZoneType = res->getUInt( "OTerritoryType" ); - ZonePtr pCurrZone = g_zoneMgr.getZone( zoneId ); + ZonePtr pCurrZone = g_territoryMgr.getZoneByTerriId( zoneId ); m_zoneId = zoneId; // TODO: logic for instances needs to be added here @@ -70,7 +72,7 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) // default to new gridania // TODO: should probably just abort and mark character as corrupt - pCurrZone = g_zoneMgr.getZone( 132 ); + pCurrZone = g_territoryMgr.getZoneByTerriId( 132 ); m_pos.x = 0.0f; m_pos.y = 0.0f; @@ -91,6 +93,11 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) m_pos.z = res->getFloat( "PosZ" ); setRotation( res->getFloat( "PosR" ) ); + m_prevPos.x = res->getFloat( "OPosX" ); + m_prevPos.y = res->getFloat( "OPosY" ); + m_prevPos.z = res->getFloat( "OPosZ" ); + m_prevRot = res->getFloat( "OPosR" ); + // Model auto custom = res->getBlobVector( "Customize" ); @@ -155,7 +162,7 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) auto orchestrion = res->getBlobVector( "Orchestrion" ); memcpy( reinterpret_cast< char* >( m_orchestrion ), orchestrion.data(), orchestrion.size() ); - + auto gcRank = res->getBlobVector( "GrandCompanyRank" ); memcpy( reinterpret_cast< char* >( m_gcRank ), gcRank.data(), gcRank.size() ); @@ -338,12 +345,12 @@ void Core::Entity::Player::updateSql() stmt->setDouble( 22, m_pos.z ); stmt->setDouble( 23, getRotation() ); - stmt->setInt( 24, 0 ); // OTerritoryType - stmt->setInt( 25, 0 ); // OTerritoryId - stmt->setDouble( 26, 0.0f ); - stmt->setDouble( 27, 0.0f ); - stmt->setDouble( 28, 0.0f ); - stmt->setDouble( 29, 0.0f ); + stmt->setInt( 24, m_prevZoneType ); // OTerritoryType + stmt->setInt( 25, m_prevZoneId ); // OTerritoryId + stmt->setDouble( 26, m_prevPos.x ); + stmt->setDouble( 27, m_prevPos.y ); + stmt->setDouble( 28, m_prevPos.z ); + stmt->setDouble( 29, m_prevRot ); stmt->setInt( 30, static_cast< uint8_t >( getClass() ) ); stmt->setInt( 31, static_cast< uint8_t >( getStatus() ) ); diff --git a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp index 5ad92c55..2902dc13 100644 --- a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp @@ -37,11 +37,13 @@ #include #include "Network/PacketWrappers/PlayerSpawnPacket.h" +#include "Zone/TerritoryMgr.h" extern Core::Scripting::ScriptManager g_scriptMgr; extern Core::Data::ExdData g_exdData; extern Core::Logger g_log; extern Core::ServerZone g_serverZone; +extern Core::TerritoryMgr g_territoryMgr; // instanciate and initialize commands Core::DebugCommandHandler::DebugCommandHandler() @@ -58,6 +60,7 @@ Core::DebugCommandHandler::DebugCommandHandler() registerCommand( "unlock", &DebugCommandHandler::unlockCharacter, "Unlock character.", 1 ); registerCommand( "help", &DebugCommandHandler::help, "Shows registered commands.", 0 ); registerCommand( "script", &DebugCommandHandler::script, "Server script utilities.", 1 ); + registerCommand( "instance", &DebugCommandHandler::instance, "Instance utilities", 1 ); } // clear all loaded commands @@ -477,7 +480,7 @@ void Core::DebugCommandHandler::get( char * data, Entity::Player& player, boost: if( ( subCommand == "pos" ) ) { - int16_t map_id = g_exdData.m_zoneInfoMap[player.getCurrentZone()->getId()].map_id; + int16_t map_id = g_exdData.m_zoneInfoMap[player.getCurrentZone()->getTerritoryId()].map_id; player.sendNotice( "Pos:\n" + std::to_string( player.getPos().x ) + "\n" + @@ -485,7 +488,7 @@ void Core::DebugCommandHandler::get( char * data, Entity::Player& player, boost: std::to_string( player.getPos().z ) + "\n" + std::to_string( player.getRotation() ) + "\nMapId: " + std::to_string( map_id ) + "\nZoneID: " + - std::to_string( player.getCurrentZone()->getId() ) + "\n" ); + std::to_string(player.getCurrentZone()->getTerritoryId() ) + "\n" ); } else { @@ -555,7 +558,7 @@ void Core::DebugCommandHandler::replay( char * data, Entity::Player& player, boo player.sendUrgent( subCommand + " is not a valid replay command." ); } - + } void Core::DebugCommandHandler::nudge( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command ) @@ -713,3 +716,50 @@ void Core::DebugCommandHandler::script( char* data, Entity::Player &player, boos player.sendDebug( "Unknown script subcommand: " + subCommand ); } } + +void Core::DebugCommandHandler::instance( char* data, Entity::Player &player, boost::shared_ptr< DebugCommand > command ) +{ + std::string cmd( data ), params, subCommand; + auto cmdPos = cmd.find_first_of( ' ' ); + + if( cmdPos != std::string::npos ) + { + params = cmd.substr( cmdPos + 1 ); + + auto p = params.find_first_of( ' ' ); + + if( p != std::string::npos ) + { + subCommand = params.substr( 0, p ); + params = params.substr( subCommand.length() + 1 ); + } + else + subCommand = params; + } + + if( subCommand == "create" || subCommand == "cr" ) + { + uint32_t instanceContentId; + sscanf( params.c_str(), "%d", &instanceContentId ); + + auto instance = g_territoryMgr.createInstanceContent( instanceContentId ); + if( instance ) + player.sendDebug( "Created instance with id: " + std::to_string( instance->getGuId() ) + " -> " + instance->getName() ); + else + player.sendDebug( "Failed to create instance with id: " + std::to_string( instanceContentId ) ); + } + else if( subCommand == "remove" || subCommand == "rm" ) + { + uint32_t terriId; + sscanf( params.c_str(), "%d", &terriId ); + + if( g_territoryMgr.removeTerritoryInstance( terriId ) ) + player.sendDebug( "Removed instance with id: " + std::to_string( terriId ) ); + else + player.sendDebug( "Failed to remove instance with id: " + std::to_string( terriId ) ); + } + else if( subCommand == "return" || subCommand == "ret" ) + { + player.exitInstance(); + } +} diff --git a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.h b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.h index cc5570e5..a0956764 100644 --- a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.h +++ b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.h @@ -44,6 +44,8 @@ public: void unlockCharacter( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command ); + void instance( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command ); + void script( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command ); }; diff --git a/src/servers/sapphire_zone/Event/Director.cpp b/src/servers/sapphire_zone/Event/Director.cpp new file mode 100644 index 00000000..79e7142b --- /dev/null +++ b/src/servers/sapphire_zone/Event/Director.cpp @@ -0,0 +1 @@ +#include "Director.h" diff --git a/src/servers/sapphire_zone/Event/Director.h b/src/servers/sapphire_zone/Event/Director.h new file mode 100644 index 00000000..8a3c0245 --- /dev/null +++ b/src/servers/sapphire_zone/Event/Director.h @@ -0,0 +1,66 @@ +#ifndef SAPPHIRE_DIRECTOR_H +#define SAPPHIRE_DIRECTOR_H + +#include + +#include "Forwards.h" + +namespace Core { +namespace Event { + +/*! +\class Director +\brief Base class for all Directors implements sequence and variables + +*/ + +class Director +{ + +public: + enum DirectorType + { + InstanceContent = 0x8003, // used for dungeons/raids + CompanyLeve = 0x8007, + QuestBattle = 0x8006, + GatheringLeve = 0x8002, + BattleLeve = 0x8001, + GoldSaucer = 0x800A, + Fate = 0x801A, + DpsChallange = 0x800D + }; + +private: + /*! Id of the content of the director */ + uint16_t m_id; + + /*! DirectorType | ContentId */ + uint32_t m_directorId; + + /*! currect sequence */ + uint8_t m_sequence; + + /*! current branch */ + uint8_t m_branch; + + /*! raw storage for flags/vars */ + uint8_t m_unionData[10]; + + /*! type of the director */ + DirectorType m_type; + + uint32_t getDirectorId() const; + uint16_t getContentId() const; + DirectorType getType() const; + uint8_t getSequence() const; + uint8_t getBranch() const; + +}; + + +} +} + + + +#endif //SAPPHIRE_DIRECTOR_H diff --git a/src/servers/sapphire_zone/Event/Event.cpp b/src/servers/sapphire_zone/Event/Event.cpp deleted file mode 100644 index ee1a3f6e..00000000 --- a/src/servers/sapphire_zone/Event/Event.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "Event.h" - -Core::Event::Event::Event( uint64_t actorId, uint32_t eventId, uint8_t eventType, uint8_t eventParam2, uint32_t eventParam3 ) - : m_actorId( actorId ), - m_eventId( eventId ), - m_playedScene( false ) -{ - - m_param1 = static_cast< uint16_t >( eventId ); - m_param2 = static_cast< uint16_t >( eventId >> 16 ); - - m_eventType = eventType; - m_eventParam2 = eventParam2; - m_eventParam3 = eventParam3; - - m_callback = nullptr; -} - -uint64_t Core::Event::Event::getActorId() const -{ - return m_actorId; -} - -uint32_t Core::Event::Event::getId() const -{ - return m_eventId; -} - -uint32_t Core::Event::Event::getParam1() const -{ - return m_param1; -} - -uint16_t Core::Event::Event::getParam2() const -{ - return m_param2; -} - -uint8_t Core::Event::Event::getEventType() const -{ - return m_eventType; -} - -uint32_t Core::Event::Event::getEventParam2() const -{ - return m_eventParam2; -} - -uint32_t Core::Event::Event::getEventParam3() const -{ - return m_eventParam3; -} - -Core::Scripting::EventReturnCallback Core::Event::Event::getEventReturnCallback() const -{ - return m_callback; -} - -void Core::Event::Event::setEventReturnCallback( Scripting::EventReturnCallback callback ) -{ - m_callback = callback; -} - - -bool Core::Event::Event::hasPlayedScene() const -{ - return m_playedScene; -} - -void Core::Event::Event::setPlayedScene( bool playedScene ) -{ - m_playedScene = playedScene; -} diff --git a/src/servers/sapphire_zone/Event/Event.h b/src/servers/sapphire_zone/Event/Event.h deleted file mode 100644 index 8935cd22..00000000 --- a/src/servers/sapphire_zone/Event/Event.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _EVENT_H -#define _EVENT_H - -#include "../Forwards.h" - -namespace Core { - namespace Event { - - class Event - { - public: - Event( uint64_t actorId, uint32_t eventId, uint8_t eventType, uint8_t eventParam2, uint32_t eventParam3 ); - - ~Event() {} - - uint64_t getActorId() const; - - uint32_t getId() const; - - uint32_t getParam1() const; - - uint16_t getParam2() const; - - uint8_t getEventType() const; - - uint32_t getEventParam2() const; - - uint32_t getEventParam3() const; - - bool hasPlayedScene() const; - - void setPlayedScene( bool playedScene ); - - Scripting::EventReturnCallback getEventReturnCallback() const; - - void setEventReturnCallback( Scripting::EventReturnCallback callback ); - - enum EventType : uint8_t - { - Talk = 1, - Emote = 2, - DistanceBelow = 3, - DistanceOver = 4, - BattleReward = 5, - Craft = 6, - Nest = 7, - Item = 8, - Drop = 9, - WithinRange = 10, - OutsideRange = 11, - GameStart = 12, - GameProgress = 13, - EnterTerritory = 15, - GameComeBack = 17, - ActionResult = 18, - MateriaCraft = 19, - Fishing = 20, - UI = 21, - Housing = 22, - Say = 23, - TableGame = 24, - }; - - protected: - uint64_t m_actorId; - uint32_t m_eventId; - uint32_t m_param1; - uint16_t m_param2; - uint8_t m_eventType; - uint8_t m_eventParam2; - uint32_t m_eventParam3; - bool m_playedScene; - Scripting::EventReturnCallback m_callback; - }; - - } -} -#endif diff --git a/src/servers/sapphire_zone/Event/EventHandler.cpp b/src/servers/sapphire_zone/Event/EventHandler.cpp new file mode 100644 index 00000000..1968f59b --- /dev/null +++ b/src/servers/sapphire_zone/Event/EventHandler.cpp @@ -0,0 +1,75 @@ +#include "EventHandler.h" + +Core::Event::EventHandler::EventHandler( Entity::Player* pOwner, uint64_t actorId, uint32_t eventId, EventType eventType, uint32_t eventParam ) : + m_pOwner( pOwner ), + m_actorId( actorId ), + m_eventId( eventId ), + m_eventType( eventType ), + m_playedScene( false ) +{ + m_entryId = static_cast< uint16_t >( eventId ); + m_type = static_cast< uint16_t >( eventId >> 16 ); + m_eventParam = eventParam; + m_callback = nullptr; +} + +uint64_t Core::Event::EventHandler::getActorId() const +{ + return m_actorId; +} + +uint32_t Core::Event::EventHandler::getId() const +{ + return m_eventId; +} + +uint8_t Core::Event::EventHandler::getEventType() const +{ + return m_eventType; +} + +uint16_t Core::Event::EventHandler::getType() const +{ + return m_type; +} + +uint16_t Core::Event::EventHandler::getEntryId() const +{ + return m_entryId; +} + +uint32_t Core::Event::EventHandler::getEventParam() const +{ + return m_eventParam; +} + +Core::Event::EventHandler::SceneReturnCallback Core::Event::EventHandler::getEventReturnCallback() const +{ + return m_callback; +} + +void Core::Event::EventHandler::setEventReturnCallback( SceneReturnCallback callback ) +{ + m_callback = callback; +} + +bool Core::Event::EventHandler::hasPlayedScene() const +{ + return m_playedScene; +} + +void Core::Event::EventHandler::setPlayedScene( bool playedScene ) +{ + m_playedScene = playedScene; +} + +bool Core::Event::EventHandler::hasNestedEvent() const +{ + return m_pNestedEvent != nullptr; +} + +void Core::Event::EventHandler::removeNestedEvent() +{ + m_pNestedEvent.reset(); +} + diff --git a/src/servers/sapphire_zone/Event/EventHandler.h b/src/servers/sapphire_zone/Event/EventHandler.h new file mode 100644 index 00000000..e02434c6 --- /dev/null +++ b/src/servers/sapphire_zone/Event/EventHandler.h @@ -0,0 +1,113 @@ +#ifndef _EVENT_H +#define _EVENT_H + +#include "../Forwards.h" + +namespace Core { + namespace Event { + + class EventHandler + { + public: + enum EventType : uint8_t + { + Talk = 1, + Emote = 2, + DistanceBelow = 3, + DistanceOver = 4, + BattleReward = 5, + Craft = 6, + Nest = 7, + Item = 8, + Drop = 9, + WithinRange = 10, + OutsideRange = 11, + GameStart = 12, + GameProgress = 13, + EnterTerritory = 15, + GameComeBack = 17, + ActionResult = 18, + MateriaCraft = 19, + Fishing = 20, + UI = 21, + Housing = 22, + Say = 23, + TableGame = 24, + }; + + enum EventHandlerType : uint16_t + { + Quest = 0x0001, + Warp = 0x0002, + Unknown = 0x0003, // Came up in the client with "Begin" unsure that means + Shop = 0x0004, + Aetheryte = 0x0005, + GuildLeveAssignment = 0x0006, + DefaultTalk = 0x0009, + CustomTalk = 0x000B, + CompanyLeveOfficer = 0x000C, + CraftLeve = 0x000E, + GimmickAccessor = 0x000F, + GimmickBill = 0x0010, + GimmickRect = 0x0011, + ChocoboTaxiStand = 0x0012, + Opening = 0x0013, + ExitRange = 0x0014, + GCShop = 0x0016, + GuildOrderGuide = 0x0017, + GuildOrderOfficer = 0x0018, + ContentNpc = 0x0019, + Story = 0x001A, + SpecialShop = 0x001B, + BahamutGuide = 0x001C, + FcTalk = 0x001F, + }; + + using SceneReturnCallback = std::function< void( Entity::Player&, uint32_t, uint16_t, uint16_t, uint16_t ) > ; + + EventHandler( Entity::Player* pOwner, uint64_t actorId, uint32_t eventId, EventType eventType, uint32_t eventParam ); + + ~EventHandler() {} + + uint64_t getActorId() const; + + uint32_t getId() const; + + uint16_t getType() const; + + uint16_t getEntryId() const; + + uint8_t getEventType() const; + + uint32_t getEventParam() const; + + bool hasPlayedScene() const; + + void setPlayedScene( bool playedScene ); + + SceneReturnCallback getEventReturnCallback() const; + + void setEventReturnCallback( SceneReturnCallback callback ); + + bool hasNestedEvent() const; + + void removeNestedEvent(); + + + protected: + Entity::Player* m_pOwner; + + uint64_t m_actorId; + uint32_t m_eventId; + uint16_t m_entryId; + uint16_t m_type; + uint8_t m_eventType; + uint32_t m_eventParam; + EventHandlerPtr m_pNestedEvent; + bool m_playedScene; + SceneReturnCallback m_callback; + }; + + } +} +#endif diff --git a/src/servers/sapphire_zone/Event/EventHelper.cpp b/src/servers/sapphire_zone/Event/EventHelper.cpp index 9d90cc3e..526faaeb 100644 --- a/src/servers/sapphire_zone/Event/EventHelper.cpp +++ b/src/servers/sapphire_zone/Event/EventHelper.cpp @@ -1,5 +1,5 @@ #include "EventHelper.h" -#include "Event.h" +#include "EventHandler.h" #include #include @@ -15,7 +15,7 @@ std::string Core::Event::getEventName( uint32_t eventId ) switch( eventType ) { - case EventType::Quest: + case Event::EventHandler::EventHandlerType::Quest: { auto questInfo = g_exdData.getQuestInfo( eventId ); if( !questInfo ) @@ -26,7 +26,7 @@ std::string Core::Event::getEventName( uint32_t eventId ) return questInfo->name_intern.substr( 0, pos ); } - case EventType::CustomTalk: + case Event::EventHandler::EventHandlerType::CustomTalk: { auto customTalkInfo = g_exdData.getCustomTalkInfo( eventId ); if( !customTalkInfo ) @@ -37,21 +37,22 @@ std::string Core::Event::getEventName( uint32_t eventId ) return customTalkInfo->name_intern.substr( 0, pos ); } - case EventType::Opening: + case Event::EventHandler::EventHandlerType::Opening: { auto openingInfo = g_exdData.getOpeningInfo( eventId ); if( openingInfo ) return openingInfo->name; return unknown + "Opening"; } - case EventType::Aetheryte: + case Event::EventHandler::EventHandlerType::Aetheryte: { auto aetherInfo = g_exdData.getAetheryteInfo( eventId & 0xFFFF ); if( aetherInfo->isAetheryte ) return "Aetheryte"; return "Aethernet"; } - case EventType::ChocoPort: + + case Event::EventHandler::EventHandlerType::Warp: { return "ChocoboTaxi"; } diff --git a/src/servers/sapphire_zone/Forwards.h b/src/servers/sapphire_zone/Forwards.h index b3dbf611..54bfaa1a 100644 --- a/src/servers/sapphire_zone/Forwards.h +++ b/src/servers/sapphire_zone/Forwards.h @@ -37,7 +37,8 @@ namespace Core namespace Event { - TYPE_FORWARD( Event ); + TYPE_FORWARD( Director ); + TYPE_FORWARD( EventHandler ); } namespace Action @@ -72,7 +73,6 @@ namespace Core namespace Scripting { class NativeScriptManager; - typedef std::function< void( Entity::Player&, uint32_t, uint16_t, uint16_t, uint16_t ) > EventReturnCallback; } typedef std::function< void( Entity::Player&, uint32_t, uint64_t ) > ActionCallback; diff --git a/src/servers/sapphire_zone/Network/GameConnection.cpp b/src/servers/sapphire_zone/Network/GameConnection.cpp index 50acbf3f..4d95a1c1 100644 --- a/src/servers/sapphire_zone/Network/GameConnection.cpp +++ b/src/servers/sapphire_zone/Network/GameConnection.cpp @@ -75,17 +75,17 @@ Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive, setZoneHandler( ClientZoneIpcType::InventoryModifyHandler,"InventoryModifyHandler", &GameConnection::inventoryModifyHandler ); - setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandler", &GameConnection::eventHandler ); - setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandler", &GameConnection::eventHandler ); - setZoneHandler( ClientZoneIpcType::WithinRangeEventHandler, "EventHandler", &GameConnection::eventHandler ); - setZoneHandler( ClientZoneIpcType::OutOfRangeEventHandler, "EventHandler", &GameConnection::eventHandler ); - setZoneHandler( ClientZoneIpcType::EnterTeriEventHandler, "EventHandler", &GameConnection::eventHandler ); + setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandlerTalk", &GameConnection::eventHandlerTalk ); + setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandlerEmote", &GameConnection::eventHandlerEmote ); + setZoneHandler( ClientZoneIpcType::WithinRangeEventHandler, "EventHandlerWithinRange", &GameConnection::eventHandlerWithinRange ); + setZoneHandler( ClientZoneIpcType::OutOfRangeEventHandler, "EventHandlerOutsideRange", &GameConnection::eventHandlerOutsideRange ); + setZoneHandler( ClientZoneIpcType::EnterTeriEventHandler, "EventHandlerEnterTeri", &GameConnection::eventHandlerEnterTerritory ); - setZoneHandler( ClientZoneIpcType::ReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandler ); - setZoneHandler( ClientZoneIpcType::TradeReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandler ); + setZoneHandler( ClientZoneIpcType::ReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandlerReturn ); + setZoneHandler( ClientZoneIpcType::TradeReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandlerReturn ); - setZoneHandler( ClientZoneIpcType::LinkshellEventHandler, "LinkshellEventHandler", &GameConnection::eventHandler ); - setZoneHandler( ClientZoneIpcType::LinkshellEventHandler1, "LinkshellEventHandler1", &GameConnection::eventHandler ); + setZoneHandler( ClientZoneIpcType::LinkshellEventHandler, "LinkshellEventHandler", &GameConnection::eventHandlerLinkshell ); + setZoneHandler( ClientZoneIpcType::LinkshellEventHandler1, "LinkshellEventHandler1", &GameConnection::eventHandlerLinkshell ); setZoneHandler( ClientZoneIpcType::CFDutyInfoHandler, "CFDutyInfoRequest", &GameConnection::cfDutyInfoRequest ); setZoneHandler( ClientZoneIpcType::CFRegisterDuty, "CFRegisterDuty", &GameConnection::cfRegisterDuty ); diff --git a/src/servers/sapphire_zone/Network/GameConnection.h b/src/servers/sapphire_zone/Network/GameConnection.h index 2d283067..8293e75c 100644 --- a/src/servers/sapphire_zone/Network/GameConnection.h +++ b/src/servers/sapphire_zone/Network/GameConnection.h @@ -99,7 +99,14 @@ public: DECLARE_HANDLER( actionHandler ); DECLARE_HANDLER( inventoryModifyHandler ); DECLARE_HANDLER( discoveryHandler ); - DECLARE_HANDLER( eventHandler ); + DECLARE_HANDLER( eventHandlerTalk ); + DECLARE_HANDLER( eventHandlerEmote ); + DECLARE_HANDLER( eventHandlerWithinRange ); + DECLARE_HANDLER( eventHandlerOutsideRange ); + DECLARE_HANDLER( eventHandlerEnterTerritory ); + DECLARE_HANDLER( eventHandlerReturn ); + DECLARE_HANDLER( eventHandlerLinkshell ); + DECLARE_HANDLER( logoutHandler ); DECLARE_HANDLER( cfDutyInfoRequest ); diff --git a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp index b1494413..90c9140a 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp @@ -13,7 +13,6 @@ #include "Zone/Zone.h" #include "Zone/ZonePosition.h" #include "ServerZone.h" -#include "Zone/ZoneMgr.h" #include "Network/PacketWrappers/InitUIPacket.h" #include "Network/PacketWrappers/PingPacket.h" @@ -37,7 +36,6 @@ extern Core::Logger g_log; extern Core::ServerZone g_serverZone; -extern Core::ZoneMgr g_zoneMgr; extern Core::Data::ExdData g_exdData; extern Core::DebugCommandHandler g_gameCommandMgr; @@ -196,7 +194,6 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in player.unsetStateFlag( PlayerStateFlag::BetweenAreas ); player.unsetStateFlag( PlayerStateFlag::BetweenAreas1 ); - player.sendStateFlags(); break; } diff --git a/src/servers/sapphire_zone/Network/Handlers/EventHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/EventHandlers.cpp index 54875ca5..e36c9717 100644 --- a/src/servers/sapphire_zone/Network/Handlers/EventHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/EventHandlers.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -20,138 +21,192 @@ #include "Forwards.h" #include "Event/EventHelper.h" +extern Core::Data::ExdData g_exdData; extern Core::Scripting::ScriptManager g_scriptMgr; using namespace Core::Common; using namespace Core::Network::Packets; using namespace Core::Network::Packets::Server; -void Core::Network::GameConnection::eventHandler( const Packets::GamePacket& inPacket, - Entity::Player& player ) +void Core::Network::GameConnection::eventHandlerTalk( const Packets::GamePacket& inPacket, Entity::Player& player ) { - uint16_t eventHandlerId = inPacket.getValAt< uint16_t >( 0x12 ); + auto actorId = inPacket.getValAt< uint64_t >( 0x20 ); + auto eventId = inPacket.getValAt< uint32_t >( 0x28 ); + auto eventType = static_cast< uint16_t >( eventId >> 16 ); - // we need to abort the event in case it has not been scripted so the player wont be locked up - auto abortEventFunc = []( Core::Entity::Player& player, uint64_t actorId, uint32_t eventId ) + std::string eventName = "onTalk"; + std::string objName = Event::getEventName( eventId ); + + player.sendDebug( "Actor: " + + std::to_string( actorId ) + " -> " + + std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) + + " \neventId: " + + std::to_string( eventId ) + + " (0x" + boost::str( boost::format( "%|08X|" ) + % static_cast< uint64_t >( eventId & 0xFFFFFFF ) ) + ")" ); + + + player.sendDebug( "Calling: " + objName + "." + eventName ); + player.eventStart( actorId, eventId, Event::EventHandler::Talk, 0, 0 ); + + if( !g_scriptMgr.onTalk( player, actorId, eventId ) && + eventType == Event::EventHandler::EventHandlerType::Quest ) { - player.queuePacket( EventStartPacket( player.getId(), actorId, eventId, 1, 0, 0 ) ); - player.queuePacket( EventFinishPacket( player.getId(), eventId, 1, 0 ) ); - // this isn't ideal as it will also reset any other status that might be active - player.queuePacket( PlayerStateFlagsPacket( player, PlayerStateFlagList{} ) ); - }; - - std::string eventIdStr = boost::str( boost::format( "%|04X|" ) % static_cast< uint32_t >( eventHandlerId & 0xFFFF ) ); - player.sendDebug( "---------------------------------------" ); - player.sendDebug( "EventHandler ( " + eventIdStr + " )" ); - - switch( eventHandlerId ) - { - - case ClientZoneIpcType::TalkEventHandler: // Talk event - { - uint64_t actorId = inPacket.getValAt< uint64_t >( 0x20 ); - uint32_t eventId = inPacket.getValAt< uint32_t >( 0x28 ); - - if( !g_scriptMgr.onTalk( player, actorId, eventId ) ) - abortEventFunc( player, actorId, eventId ); - break; + auto questInfo = g_exdData.getQuestInfo( eventId ); + if ( questInfo ) + player.sendUrgent( "Quest not implemented: " + questInfo->name + " (" + questInfo->name_intern + ")" ); } - case ClientZoneIpcType::EmoteEventHandler: // Emote event + player.checkEvent( eventId ); + +} + +void Core::Network::GameConnection::eventHandlerEmote( const Packets::GamePacket& inPacket, Entity::Player& player ) +{ + + auto actorId = inPacket.getValAt< uint64_t >( 0x20 ); + auto eventId = inPacket.getValAt< uint32_t >( 0x28 ); + auto emoteId = inPacket.getValAt< uint16_t >( 0x2C ); + auto eventType = static_cast< uint16_t >( eventId >> 16 ); + + std::string eventName = "onEmote"; + std::string objName = Event::getEventName( eventId ); + + player.sendDebug( "Actor: " + + std::to_string( actorId ) + " -> " + + std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) + + " \neventId: " + + std::to_string( eventId ) + + " (0x" + boost::str( boost::format( "%|08X|" ) + % static_cast< uint64_t >( eventId & 0xFFFFFFF ) ) + ")" ); + + player.sendDebug( "Calling: " + objName + "." + eventName ); + + player.eventStart( actorId, eventId, Event::EventHandler::Emote, 0, emoteId ); + + if( !g_scriptMgr.onEmote( player, actorId, eventId, static_cast< uint8_t >( emoteId ) ) && + eventType == Event::EventHandler::EventHandlerType::Quest ) { - uint64_t actorId = inPacket.getValAt< uint64_t >( 0x20 ); - uint32_t eventId = inPacket.getValAt< uint32_t >( 0x28 ); - uint16_t emoteId = inPacket.getValAt< uint16_t >( 0x2C ); - - std::string eventName = Event::getEventName( eventId ); - - if( !g_scriptMgr.onEmote( player, actorId, eventId, static_cast< uint8_t >( emoteId ) ) ) - abortEventFunc( player, actorId, eventId ); - break; + auto questInfo = g_exdData.getQuestInfo( eventId ); + if( questInfo ) + player.sendUrgent( "Quest not implemented: " + questInfo->name ); } + player.checkEvent( eventId ); +} - case ClientZoneIpcType::WithinRangeEventHandler: +void Core::Network::GameConnection::eventHandlerWithinRange( const Packets::GamePacket& inPacket, + Entity::Player& player ) +{ + + auto eventId = inPacket.getValAt< uint32_t >( 0x24 ); + auto param1 = inPacket.getValAt< uint32_t >( 0x20 ); + auto x = inPacket.getValAt< float >( 0x28 ); + auto y = inPacket.getValAt< float >( 0x2C ); + auto z = inPacket.getValAt< float >( 0x30 ); + + std::string eventName = "onWithinRange"; + std::string objName = Event::getEventName( eventId ); + player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) + + " p1: " + std::to_string( param1 ) ); + + player.eventStart( player.getId(), eventId, Event::EventHandler::WithinRange, 1, param1 ); + + g_scriptMgr.onWithinRange( player, eventId, param1, x, y, z ); + + player.checkEvent( eventId ); +} + +void Core::Network::GameConnection::eventHandlerOutsideRange( const Packets::GamePacket& inPacket, + Entity::Player& player ) +{ + + auto eventId = inPacket.getValAt< uint32_t >( 0x24 ); + auto param1 = inPacket.getValAt< uint32_t >( 0x20 ); + auto x = inPacket.getValAt< float >( 0x28 ); + auto y = inPacket.getValAt< float >( 0x2C ); + auto z = inPacket.getValAt< float >( 0x30 ); + + std::string eventName = "onOutsideRange"; + std::string objName = Event::getEventName( eventId ); + player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) + + " p1: " + std::to_string( param1 ) ); + + player.eventStart( player.getId(), eventId, Event::EventHandler::WithinRange, 1, param1 ); + + g_scriptMgr.onOutsideRange( player, eventId, param1, x, y, z ); + + player.checkEvent( eventId ); +} + +void Core::Network::GameConnection::eventHandlerEnterTerritory( const Packets::GamePacket &inPacket, + Entity::Player &player ) +{ + auto eventId = inPacket.getValAt< uint32_t >( 0x20 ); + auto param1 = inPacket.getValAt< uint16_t >( 0x24 ); + auto param2 = inPacket.getValAt< uint16_t >( 0x26 ); + + std::string eventName = Event::getEventName( eventId ); + + std::string objName = Event::getEventName( eventId ); + + player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) ); + + player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId() ); + + g_scriptMgr.onEnterTerritory( player, eventId, param1, param2 ); + + player.checkEvent( eventId ); +} + +void Core::Network::GameConnection::eventHandlerReturn( const Packets::GamePacket &inPacket, + Entity::Player &player ) +{ + auto eventId = inPacket.getValAt< uint32_t >( 0x20 ); + auto scene = inPacket.getValAt< uint16_t >( 0x24 ); + auto param1 = inPacket.getValAt< uint16_t >( 0x26 ); + auto param2 = inPacket.getValAt< uint16_t >( 0x28 ); + auto param3 = inPacket.getValAt< uint16_t >( 0x2C ); + + std::string eventName = Event::getEventName( eventId ); + + player.sendDebug( "eventId: " + + std::to_string( eventId ) + + " ( 0x" + boost::str( boost::format( "%|08X|" ) % ( uint64_t ) ( eventId & 0xFFFFFFF ) ) + " ) " + + " scene: " + std::to_string( scene ) + + " p1: " + std::to_string( param1 ) + + " p2: " + std::to_string( param2 ) + + " p3: " + std::to_string( param3 ) ); + + auto pEvent = player.getEvent( eventId ); + if( pEvent ) { - uint32_t eventId = inPacket.getValAt< uint32_t >( 0x24 ); - uint32_t eventParam1 = inPacket.getValAt< uint32_t >( 0x20 ); - float x = inPacket.getValAt< float >( 0x28 ); - float y = inPacket.getValAt< float >( 0x2C ); - float z = inPacket.getValAt< float >( 0x30 ); - - std::string eventName = Event::getEventName( eventId ); - - if( !g_scriptMgr.onWithinRange( player, eventId, eventParam1, x, y, z ) ) - abortEventFunc( player, 0, eventId ); - break; + pEvent->setPlayedScene( false ); + // try to retrieve a stored callback + auto eventCallback = pEvent->getEventReturnCallback(); + // if there is one, proceed to call it + if( eventCallback ) + eventCallback( player, eventId, param1, param2, param3 ); } - case ClientZoneIpcType::OutOfRangeEventHandler: - { - uint32_t eventId = inPacket.getValAt< uint32_t >( 0x24 ); - uint32_t eventParam1 = inPacket.getValAt< uint32_t >( 0x20 ); - float x = inPacket.getValAt< float >( 0x28 ); - float y = inPacket.getValAt< float >( 0x2C ); - float z = inPacket.getValAt< float >( 0x30 ); + player.checkEvent( eventId ); - std::string eventName = Event::getEventName( eventId ); +} - if( !g_scriptMgr.onOutsideRange( player, eventId, eventParam1, x, y, z ) ) - abortEventFunc( player, 0, eventId ); - break; - } +void Core::Network::GameConnection::eventHandlerLinkshell( const Packets::GamePacket &inPacket, + Entity::Player &player ) +{ + auto eventId = inPacket.getValAt< uint32_t >( 0x20 ); + auto scene = inPacket.getValAt< uint16_t >( 0x24 ); + auto lsName = inPacket.getStringAt( 0x27 ); - case ClientZoneIpcType::EnterTeriEventHandler: - { - uint32_t eventId = inPacket.getValAt< uint32_t >( 0x20 ); - uint16_t eventParam1 = inPacket.getValAt< uint16_t >( 0x24 ); - uint16_t eventParam2 = inPacket.getValAt< uint16_t >( 0x26 ); - - std::string eventName = Event::getEventName( eventId ); - - if( !g_scriptMgr.onEnterTerritory( player, eventId, eventParam1, eventParam2 ) ) - abortEventFunc( player, 0, eventId ); - break; - } - - case ClientZoneIpcType::ReturnEventHandler: - case ClientZoneIpcType::TradeReturnEventHandler: - { - uint32_t eventId = inPacket.getValAt< uint32_t >( 0x20 ); - uint16_t subEvent = inPacket.getValAt< uint16_t >( 0x24 ); - uint16_t param1 = inPacket.getValAt< uint16_t >( 0x26 ); - uint16_t param2 = inPacket.getValAt< uint16_t >( 0x28 ); - uint16_t param3 = inPacket.getValAt< uint16_t >( 0x2C ); - - std::string eventName = Event::getEventName( eventId ); - - if( !g_scriptMgr.onEventHandlerReturn( player, eventId, subEvent, param1, param2, param3 ) ) - abortEventFunc( player, 0, eventId ); - break; - } - - case ClientZoneIpcType::LinkshellEventHandler: - case ClientZoneIpcType::LinkshellEventHandler1: - { - uint32_t eventId = inPacket.getValAt< uint32_t >( 0x20 ); - uint16_t subEvent = inPacket.getValAt< uint16_t >( 0x24 ); - std::string lsName = inPacket.getStringAt( 0x27 ); - - ZoneChannelPacket< FFXIVIpcEventLinkshell > linkshellEvent( player.getId() ); - linkshellEvent.data().eventId = eventId; - linkshellEvent.data().scene = static_cast< uint8_t >( subEvent ); - linkshellEvent.data().param3 = 1; - linkshellEvent.data().unknown1 = 0x15a; - player.queuePacket( linkshellEvent ); - -// abortEventFunc( pPlayer, 0, eventId ); - break; - } - - } + ZoneChannelPacket< FFXIVIpcEventLinkshell > linkshellEvent( player.getId() ); + linkshellEvent.data().eventId = eventId; + linkshellEvent.data().scene = static_cast< uint8_t >( scene ); + linkshellEvent.data().param3 = 1; + linkshellEvent.data().unknown1 = 0x15a; + player.queuePacket( linkshellEvent ); } - - diff --git a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp index 15dc09fc..d3226c3a 100644 --- a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp @@ -10,10 +10,10 @@ #include "Network/GameConnection.h" #include "Session.h" +#include "Zone/TerritoryMgr.h" #include "Zone/Zone.h" #include "Zone/ZonePosition.h" #include "ServerZone.h" -#include "Zone/ZoneMgr.h" #include "Network/PacketWrappers/InitUIPacket.h" #include "Network/PacketWrappers/PingPacket.h" @@ -37,7 +37,7 @@ extern Core::Logger g_log; extern Core::ServerZone g_serverZone; -extern Core::ZoneMgr g_zoneMgr; +extern Core::TerritoryMgr g_territoryMgr; extern Core::Data::ExdData g_exdData; extern Core::DebugCommandHandler g_gameCommandMgr; @@ -403,16 +403,27 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } case GmCommand::Teri: { - auto zoneInfo = g_zoneMgr.getZone( param1 ); - if ( !zoneInfo ) + if( auto instance = g_territoryMgr.getInstanceZonePtr( param1 ) ) + { + player.sendDebug( "Found instance: " + instance->getName() + ", id: " + std::to_string( param1 ) ); + + player.setInstance( instance ); + } + else if( !g_territoryMgr.isValidTerritory( param1 ) ) { player.sendUrgent( "Invalid zone " + std::to_string( param1 ) ); } else { + auto pZone = g_territoryMgr.getZoneByTerriId( param1 ); + if( !pZone ) + { + player.sendUrgent( "No zone instance found for " + std::to_string( param1 ) ); + break; + } targetPlayer->setPosition( targetPlayer->getPos() ); targetPlayer->performZoning( param1, targetPlayer->getPos(), 0 ); - player.sendNotice( targetPlayer->getName() + " was warped to zone " + std::to_string( param1 ) + " (" + zoneInfo->getName( ) + ")" ); + player.sendNotice( targetPlayer->getName() + " was warped to zone " + std::to_string( param1 ) + " (" + pZone->getName() + ")" ); } break; } @@ -438,7 +449,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac player.sendNotice( "Jumping to " + targetPlayer->getName() + " in range." ); break; } - + default: player.sendUrgent( "GM1 Command not implemented: " + std::to_string( commandId ) ); break; diff --git a/src/servers/sapphire_zone/Network/Handlers/InventoryHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/InventoryHandler.cpp index 3f87d2ab..752ca776 100644 --- a/src/servers/sapphire_zone/Network/Handlers/InventoryHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/InventoryHandler.cpp @@ -13,7 +13,6 @@ #include "Zone/Zone.h" #include "Zone/ZonePosition.h" #include "ServerZone.h" -#include "Zone/ZoneMgr.h" #include "Network/PacketWrappers/ServerNoticePacket.h" #include "Network/PacketWrappers/ActorControlPacket142.h" @@ -27,7 +26,6 @@ extern Core::Logger g_log; extern Core::ServerZone g_serverZone; -extern Core::ZoneMgr g_zoneMgr; extern Core::Data::ExdData g_exdData; extern Core::DebugCommandHandler g_gameCommandMgr; diff --git a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp index fe58f3aa..31495441 100644 --- a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp @@ -12,10 +12,10 @@ #include "Network/GameConnection.h" #include "Session.h" +#include "ServerZone.h" +#include "Zone/TerritoryMgr.h" #include "Zone/Zone.h" #include "Zone/ZonePosition.h" -#include "ServerZone.h" -#include "Zone/ZoneMgr.h" #include "Network/PacketWrappers/InitUIPacket.h" #include "Network/PacketWrappers/PingPacket.h" @@ -40,7 +40,7 @@ extern Core::Logger g_log; extern Core::ServerZone g_serverZone; -extern Core::ZoneMgr g_zoneMgr; +extern Core::TerritoryMgr g_territoryMgr; extern Core::Data::ExdData g_exdData; extern Core::DebugCommandHandler g_gameCommandMgr; @@ -297,7 +297,7 @@ void Core::Network::GameConnection::zoneLineHandler( const Packets::GamePacket& auto pZone = player.getCurrentZone(); - auto pLine = g_zoneMgr.getZonePosition( zoneLineId ); + auto pLine = g_territoryMgr.getTerritoryPosition( zoneLineId ); Common::FFXIVARR_POSITION3 targetPos{}; uint32_t targetZone; @@ -324,7 +324,7 @@ void Core::Network::GameConnection::zoneLineHandler( const Packets::GamePacket& targetPos.x = 0; targetPos.y = 0; targetPos.z = 0; - targetZone = pZone->getId(); + targetZone = pZone->getTerritoryId(); } player.performZoning( targetZone, targetPos, rotation); @@ -442,7 +442,7 @@ void Core::Network::GameConnection::socialListHandler( const Packets::GamePacket int32_t entrysizes = sizeof( listPacket.data().entries ); memset( listPacket.data().entries, 0, sizeof( listPacket.data().entries ) ); - listPacket.data().entries[0].bytes[2] = player.getCurrentZone()->getId(); + listPacket.data().entries[0].bytes[2] = player.getCurrentZone()->getTerritoryId(); listPacket.data().entries[0].bytes[3] = 0x80; listPacket.data().entries[0].bytes[4] = 0x02; listPacket.data().entries[0].bytes[6] = 0x3B; @@ -450,7 +450,7 @@ void Core::Network::GameConnection::socialListHandler( const Packets::GamePacket listPacket.data().entries[0].classJob = static_cast< uint8_t >( player.getClass() ); listPacket.data().entries[0].contentId = player.getContentId(); listPacket.data().entries[0].level = player.getLevel(); - listPacket.data().entries[0].zoneId = player.getCurrentZone()->getId(); + listPacket.data().entries[0].zoneId = player.getCurrentZone()->getTerritoryId(); listPacket.data().entries[0].zoneId1 = 0x0100; // TODO: no idea what this does //listPacket.data().entries[0].one = 1; diff --git a/src/servers/sapphire_zone/Script/NativeScriptApi.h b/src/servers/sapphire_zone/Script/NativeScriptApi.h index 65d317d4..72c0fac6 100644 --- a/src/servers/sapphire_zone/Script/NativeScriptApi.h +++ b/src/servers/sapphire_zone/Script/NativeScriptApi.h @@ -2,6 +2,9 @@ #define NATIVE_SCRIPT_API #include +#include +#include + #include #include #include @@ -18,41 +21,24 @@ using namespace Core; #define EVENTSCRIPT_AETHERYTE_ID 0x50000 #define EVENTSCRIPT_AETHERNET_ID 0x50001 -enum ScriptType -{ - None, - ScriptedStatusEffect, - ScriptedAction, - ScriptedEvent, - ScriptedBattleNpc, - ScriptedZone -}; - class ScriptObject { protected: - std::string m_scriptName; uint32_t m_id; - ScriptType m_type; + std::size_t m_type; public: - ScriptObject( std::string name, uint32_t id, ScriptType type ) : - m_scriptName( name ), + ScriptObject( uint32_t id, std::size_t type ) : m_id( id ), m_type( type ) { } - virtual const std::string& getName() const - { - return m_scriptName; - } - virtual uint32_t getId() const { return m_id; } - virtual ScriptType getType() const + virtual std::size_t getType() const { return m_type; } @@ -62,8 +48,8 @@ public: class StatusEffectScript : public ScriptObject { public: - StatusEffectScript( std::string name, uint32_t effectId ) : - ScriptObject( name, effectId, ScriptType::ScriptedStatusEffect ) + StatusEffectScript( uint32_t effectId ) : + ScriptObject( effectId, typeid( StatusEffectScript ).hash_code() ) { } virtual void onTick( Entity::Actor& actor ) { } @@ -80,8 +66,8 @@ public: class ActionScript : public ScriptObject { public: - ActionScript( std::string name, uint32_t abilityId ) : - ScriptObject( name, abilityId, ScriptType::ScriptedAction ) + ActionScript( uint32_t abilityId ) : + ScriptObject( abilityId, typeid( ActionScript ).hash_code() ) { } virtual void onStart( Entity::Actor& sourceActor, Entity::Actor& targetActor ) { } @@ -93,8 +79,8 @@ public: class EventScript : public ScriptObject { public: - EventScript( std::string name, uint32_t questId ) : - ScriptObject( name, questId, ScriptType::ScriptedEvent ) + EventScript( uint32_t questId ) : + ScriptObject( questId, typeid( EventScript ).hash_code() ) { } virtual void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) { } @@ -111,16 +97,16 @@ public: class BattleNpcScript : public ScriptObject { public: - BattleNpcScript( std::string name, uint32_t npcId ) : - ScriptObject( name, npcId, ScriptType::ScriptedBattleNpc ) + BattleNpcScript( uint32_t npcId ) : + ScriptObject( npcId, typeid( BattleNpcScript ).hash_code() ) { } }; class ZoneScript : public ScriptObject { public: - ZoneScript( std::string name, uint32_t zoneId ) : - ScriptObject( name, zoneId, ScriptType::ScriptedZone ) + ZoneScript( uint32_t zoneId ) : + ScriptObject( zoneId, typeid( ZoneScript ).hash_code() ) { } virtual void onZoneInit() { } diff --git a/src/servers/sapphire_zone/Script/NativeScriptManager.h b/src/servers/sapphire_zone/Script/NativeScriptManager.h index af3e256c..a793b68e 100644 --- a/src/servers/sapphire_zone/Script/NativeScriptManager.h +++ b/src/servers/sapphire_zone/Script/NativeScriptManager.h @@ -19,7 +19,7 @@ namespace Scripting { class NativeScriptManager { protected: - std::unordered_map< ScriptType, std::unordered_map< uint32_t, ScriptObject* > > m_scripts; + std::unordered_map< std::size_t, std::unordered_map< uint32_t, ScriptObject* > > m_scripts; ScriptLoader m_loader; @@ -40,11 +40,11 @@ namespace Scripting { const std::string getModuleExtension(); bool isModuleLoaded( const std::string& name ); - // todo: use some template magic (type_traits is_same?) to avoid ScriptType param - // not sure if worthwhile given that it adds an extra place where script types need to be managed template< typename T > - T* getScript( ScriptType type, uint32_t scriptId ) + T* getScript( uint32_t scriptId ) { + auto type = typeid( T ).hash_code(); + auto script = m_scripts[type].find( scriptId ); if( script == m_scripts[type].end() ) return nullptr; diff --git a/src/servers/sapphire_zone/Script/ScriptInfo.h b/src/servers/sapphire_zone/Script/ScriptInfo.h index 7ddabc18..f57c1a7c 100644 --- a/src/servers/sapphire_zone/Script/ScriptInfo.h +++ b/src/servers/sapphire_zone/Script/ScriptInfo.h @@ -26,7 +26,6 @@ namespace Scripting { ModuleHandle handle; std::vector< ScriptObject* > scripts; - ScriptType type; }; } } diff --git a/src/servers/sapphire_zone/Script/ScriptManager.cpp b/src/servers/sapphire_zone/Script/ScriptManager.cpp index 5188ae23..40eddee6 100644 --- a/src/servers/sapphire_zone/Script/ScriptManager.cpp +++ b/src/servers/sapphire_zone/Script/ScriptManager.cpp @@ -8,7 +8,7 @@ #include "Actor/Player.h" #include "Actor/BattleNpc.h" #include "ServerZone.h" -#include "Event/Event.h" +#include "Event/EventHandler.h" #include "Event/EventHelper.h" #include "StatusEffect/StatusEffect.h" #include "Network/PacketWrappers/ServerNoticePacket.h" @@ -74,6 +74,10 @@ bool Core::Scripting::ScriptManager::init() void Core::Scripting::ScriptManager::watchDirectories() { + auto shouldWatch = g_serverZone.getConfig()->getValue< bool >( "Settings.General.Scripts.HotSwap.Enabled", true ); + if( !shouldWatch ) + return; + Watchdog::watchMany( g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Scripts.Path", "./compiledscripts/" ) + "*" + m_nativeScriptManager->getModuleExtension(), [ this ]( const std::vector< ci::fs::path >& paths ) { @@ -143,22 +147,12 @@ bool Core::Scripting::ScriptManager::registerBnpcTemplate( std::string templateN bool Core::Scripting::ScriptManager::onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId ) { - std::string eventName = "onTalk"; - std::string objName = Event::getEventName( eventId ); - - player.sendDebug( "Actor: " + - std::to_string( actorId ) + " -> " + - std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) + - " \neventId: " + - std::to_string( eventId ) + - " (0x" + boost::str( boost::format( "%|08X|" ) - % static_cast< uint64_t >( eventId & 0xFFFFFFF ) ) + ")" ); uint16_t eventType = eventId >> 16; uint32_t scriptId = eventId; // aethernet/aetherytes need to be handled separately - if( eventType == Common::EventType::Aetheryte ) + if( eventType == Event::EventHandler::EventHandlerType::Aetheryte ) { auto aetherInfo = g_exdData.getAetheryteInfo( eventId & 0xFFFF ); scriptId = EVENTSCRIPT_AETHERYTE_ID; @@ -166,136 +160,50 @@ bool Core::Scripting::ScriptManager::onTalk( Entity::Player& player, uint64_t ac scriptId = EVENTSCRIPT_AETHERNET_ID; } - auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, scriptId ); - if( script ) - { - player.sendDebug( "Calling: " + objName + "." + eventName ); - - player.eventStart( actorId, eventId, Event::Event::Talk, 0, 0 ); - - script->onTalk( eventId, player, actorId ); - - player.checkEvent( eventId ); - } - else - { - if ( eventType == Common::EventType::Quest ) - { - auto questInfo = g_exdData.getQuestInfo( eventId ); - if ( questInfo ) - { - player.sendUrgent( "Quest not implemented: " + questInfo->name + " (" + questInfo->name_intern + ")" ); - - } - } - + auto script = m_nativeScriptManager->getScript< EventScript >( scriptId ); + if( !script ) return false; - } - + script->onTalk( eventId, player, actorId ); return true; } bool Core::Scripting::ScriptManager::onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) { - std::string eventName = "onEnterTerritory"; - std::string objName = Event::getEventName( eventId ); - - player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) ); - - auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); - if( script ) - { - player.eventStart( player.getId(), eventId, Event::Event::EnterTerritory, 0, player.getZoneId() ); - - script->onEnterZone( player, eventId, param1, param2 ); - - player.checkEvent( eventId ); - - return true; - } - - return false; + auto script = m_nativeScriptManager->getScript< EventScript >( eventId ); + if( !script ) + return false; + script->onEnterZone( player, eventId, param1, param2 ); + return true; } bool Core::Scripting::ScriptManager::onWithinRange( Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z ) { - - std::string eventName = "onWithinRange"; - std::string objName = Event::getEventName( eventId ); - player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) + " p1: " + std::to_string( param1 ) ); - - auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); - if( script ) - { - player.eventStart( player.getId(), eventId, Event::Event::WithinRange, 1, param1 ); - - script->onWithinRange( player, eventId, param1, x, y, z ); - - player.checkEvent( eventId ); - - return true; - } - - return false; + auto script = m_nativeScriptManager->getScript< EventScript >( eventId ); + if( !script ) + return false; + script->onWithinRange( player, eventId, param1, x, y, z ); + return true; } bool Core::Scripting::ScriptManager::onOutsideRange( Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z ) { - std::string eventName = "onOutsideRange"; - std::string objName = Event::getEventName( eventId ); - player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) ); - - auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); - if( script ) - { - player.eventStart( player.getId(), eventId, Event::Event::WithinRange, 1, param1 ); - - script->onOutsideRange( player, eventId, param1, x, y, z ); - - player.checkEvent( eventId ); - - return true; - } - - return false; + auto script = m_nativeScriptManager->getScript< EventScript >( eventId ); + if( !script ) + return false; + script->onOutsideRange( player, eventId, param1, x, y, z ); + return true; } bool Core::Scripting::ScriptManager::onEmote( Entity::Player& player, uint64_t actorId, uint32_t eventId, uint8_t emoteId ) { - std::string eventName = "onEmote"; - std::string objName = Event::getEventName( eventId ); - - auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); - if( script ) - { - player.sendDebug( "Calling: " + objName + "." + eventName ); - - player.eventStart( actorId, eventId, Event::Event::Emote, 0, emoteId ); - - script->onEmote( actorId, eventId, emoteId, player ); - - player.checkEvent( eventId ); - } - else - { - uint16_t eventType = eventId >> 16; - - if( eventType == Common::EventType::Quest ) - { - auto questInfo = g_exdData.getQuestInfo( eventId ); - if( questInfo ) - { - player.sendUrgent( "Quest not implemented: " + questInfo->name ); - return false; - } - } + auto script = m_nativeScriptManager->getScript< EventScript >( eventId ); + if( !script ) return false; - } - + script->onEmote( actorId, eventId, emoteId, player ); return true; } @@ -304,53 +212,16 @@ bool Core::Scripting::ScriptManager::onEventHandlerReturn( Entity::Player& playe uint16_t param3 ) { - player.sendDebug( "eventId: " + - std::to_string( eventId ) + - " ( 0x" + boost::str( boost::format( "%|08X|" ) % ( uint64_t ) ( eventId & 0xFFFFFFF ) ) + " ) " + - " scene: " + std::to_string( subEvent ) + - " p1: " + std::to_string( param1 ) + - " p2: " + std::to_string( param2 ) + - " p3: " + std::to_string( param3 ) ); - - try - { - auto pEvent = player.getEvent( eventId ); - if( pEvent ) - { - pEvent->setPlayedScene( false ); - // try to retrieve a stored callback - auto eventCallback = pEvent->getEventReturnCallback(); - // if there is one, proceed to call it - if( eventCallback ) - { - eventCallback( player, eventId, param1, param2, param3 ); - if( !pEvent->hasPlayedScene() ) - player.eventFinish( eventId, 1 ); - else - pEvent->setPlayedScene( false ); - } - // else, finish the event. - else - player.eventFinish( eventId, 1 ); - } - } - catch( std::exception& e ) - { - player.sendNotice( e.what() ); - return false; - } - - return true; + return false; } bool Core::Scripting::ScriptManager::onEventHandlerTradeReturn( Entity::Player& player, uint32_t eventId, uint16_t subEvent, uint16_t param, uint32_t catalogId ) { - auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); + auto script = m_nativeScriptManager->getScript< EventScript >( eventId ); if( script ) { script->onEventHandlerTradeReturn( player, eventId, subEvent, param, catalogId ); - return true; } @@ -364,13 +235,12 @@ bool Core::Scripting::ScriptManager::onEventItem( Entity::Player& player, uint32 std::string objName = Event::getEventName( eventId ); player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) ); - auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, eventId ); + auto script = m_nativeScriptManager->getScript< EventScript >( eventId ); if( script ) { - player.eventStart( targetId, eventId, Event::Event::Item, 0, 0 ); + player.eventStart( targetId, eventId, Event::EventHandler::Item, 0, 0 ); script->onEventItem( player, eventItemId, eventId, castTime, targetId ); - return true; } @@ -391,7 +261,7 @@ bool Core::Scripting::ScriptManager::onMobKill( Entity::Player& player, uint16_t uint16_t questId = activeQuests->c.questId; - auto script = m_nativeScriptManager->getScript< EventScript >( ScriptType::ScriptedEvent, questId ); + auto script = m_nativeScriptManager->getScript< EventScript >( questId ); if( script ) { std::string objName = Event::getEventName( 0x00010000 | questId ); @@ -407,17 +277,16 @@ bool Core::Scripting::ScriptManager::onMobKill( Entity::Player& player, uint16_t bool Core::Scripting::ScriptManager::onCastFinish( Entity::Player& player, Entity::ActorPtr pTarget, uint32_t actionId ) { - auto script = m_nativeScriptManager->getScript< ActionScript >( ScriptType::ScriptedAction, actionId ); + auto script = m_nativeScriptManager->getScript< ActionScript >( actionId ); if( script ) script->onCastFinish( player, *pTarget ); - return true; } bool Core::Scripting::ScriptManager::onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId ) { - auto script = m_nativeScriptManager->getScript< StatusEffectScript >( ScriptType::ScriptedStatusEffect, effectId ); + auto script = m_nativeScriptManager->getScript< StatusEffectScript >( effectId ); if( script ) { @@ -425,7 +294,6 @@ bool Core::Scripting::ScriptManager::onStatusReceive( Entity::ActorPtr pActor, u pActor->getAsPlayer()->sendDebug( "Calling status receive for statusid: " + std::to_string( effectId ) ); script->onApply( *pActor ); - return true; } @@ -434,14 +302,13 @@ bool Core::Scripting::ScriptManager::onStatusReceive( Entity::ActorPtr pActor, u bool Core::Scripting::ScriptManager::onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect ) { - auto script = m_nativeScriptManager->getScript< StatusEffectScript >( ScriptType::ScriptedStatusEffect, effect.getId() ); + auto script = m_nativeScriptManager->getScript< StatusEffectScript >( effect.getId() ); if( script ) { if( pActor->isPlayer() ) pActor->getAsPlayer()->sendDebug( "Calling status tick for statusid: " + std::to_string( effect.getId() ) ); script->onTick( *pActor ); - return true; } @@ -450,14 +317,13 @@ bool Core::Scripting::ScriptManager::onStatusTick( Entity::ActorPtr pActor, Core bool Core::Scripting::ScriptManager::onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId ) { - auto script = m_nativeScriptManager->getScript< StatusEffectScript >( ScriptType::ScriptedStatusEffect, effectId ); + auto script = m_nativeScriptManager->getScript< StatusEffectScript >( effectId ); if( script ) { if( pActor->isPlayer() ) pActor->getAsPlayer()->sendDebug( "Calling status timeout for statusid: " + std::to_string( effectId ) ); script->onExpire( *pActor ); - return true; } @@ -466,11 +332,10 @@ bool Core::Scripting::ScriptManager::onStatusTimeOut( Entity::ActorPtr pActor, u bool Core::Scripting::ScriptManager::onZoneInit( ZonePtr pZone ) { - auto script = m_nativeScriptManager->getScript< ZoneScript >( ScriptType::ScriptedZone, pZone->getId() ); + auto script = m_nativeScriptManager->getScript< ZoneScript >(pZone->getTerritoryId() ); if( script ) { script->onZoneInit(); - return true; } diff --git a/src/servers/sapphire_zone/ServerZone.cpp b/src/servers/sapphire_zone/ServerZone.cpp index d97a7d33..712fa37d 100644 --- a/src/servers/sapphire_zone/ServerZone.cpp +++ b/src/servers/sapphire_zone/ServerZone.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -21,7 +22,7 @@ #include "Network/GameConnection.h" #include "Session.h" -#include "Zone/ZoneMgr.h" +#include "Zone/TerritoryMgr.h" #include "DebugCommand/DebugCommandHandler.h" @@ -33,12 +34,14 @@ #include #include #include +#include Core::Logger g_log; Core::DebugCommandHandler g_gameCommandMgr; Core::Scripting::ScriptManager g_scriptMgr; Core::Data::ExdData g_exdData; -Core::ZoneMgr g_zoneMgr; +Core::Data::ExdDataGenerated g_exdDataGen; +Core::TerritoryMgr g_territoryMgr; Core::LinkshellMgr g_linkshellMgr; Core::Db::DbWorkerPool< Core::Db::CharaDbConnection > g_charaDb; @@ -168,6 +171,13 @@ bool Core::ServerZone::loadSettings( int32_t argc, char* argv[] ) return false; } + g_log.info( "Setting up generated EXD data" ); + if( !g_exdDataGen.init( m_pConfig->getValue< std::string >( "Settings.General.DataPath", "" ) ) ) + { + g_log.fatal( "Error setting up generated EXD data " ); + return false; + } + Core::Db::DbLoader loader; Core::Db::ConnectionInfo info; @@ -224,8 +234,8 @@ void Core::ServerZone::run( int32_t argc, char* argv[] ) g_scriptMgr.init(); - g_log.info( "ZoneMgr: Setting up zones" ); - g_zoneMgr.createZones(); + g_log.info( "TerritoryMgr: Setting up zones" ); + g_territoryMgr.init(); std::vector< std::thread > thread_list; thread_list.emplace_back( std::thread( std::bind( &Network::Hive::Run, hive.get() ) ) ); @@ -258,12 +268,13 @@ void Core::ServerZone::mainLoop() { this_thread::sleep_for( chrono::milliseconds( 50 ) ); - g_zoneMgr.updateZones(); + + auto currTime = static_cast< uint32_t >( Util::getTimeSeconds() ); + + g_territoryMgr.updateTerritoryInstances( currTime ); g_scriptMgr.update(); - auto currTime = static_cast< uint32_t >( time( nullptr ) ); - lock_guard< std::mutex > lock( this->m_sessionMutex ); for( auto sessionIt : this->m_sessionMapById ) { diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.cpp b/src/servers/sapphire_zone/Zone/InstanceContent.cpp new file mode 100644 index 00000000..0512eecb --- /dev/null +++ b/src/servers/sapphire_zone/Zone/InstanceContent.cpp @@ -0,0 +1,29 @@ +#include "InstanceContent.h" + +Core::InstanceContent::InstanceContent( boost::shared_ptr< Core::Data::InstanceContent > pInstanceContent, + uint32_t guId, + const std::string& internalName, + const std::string& contentName, + uint32_t instanceContentId ) + : Zone( pInstanceContent->territoryType, guId, internalName, contentName ), + m_instanceContentInfo( pInstanceContent ), + m_instanceContentId( instanceContentId ), + m_state( Created ) +{ + +} + +Core::InstanceContent::~InstanceContent() +{ + +} + +uint32_t Core::InstanceContent::getInstanceContentId() const +{ + return m_instanceContentId; +} + +boost::shared_ptr< Core::Data::InstanceContent > Core::InstanceContent::getInstanceContentInfo() const +{ + return m_instanceContentInfo; +} diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.h b/src/servers/sapphire_zone/Zone/InstanceContent.h new file mode 100644 index 00000000..da52f5e0 --- /dev/null +++ b/src/servers/sapphire_zone/Zone/InstanceContent.h @@ -0,0 +1,41 @@ +#ifndef SAPPHIRE_INSTANCECONTENT_H +#define SAPPHIRE_INSTANCECONTENT_H + +#include "Zone.h" +#include "Forwards.h" +#include + +namespace Core +{ + +class InstanceContent : public Zone +{ +public: + enum InstanceContentState + { + Created, + DutyStarted, + DutyFinished + }; + + InstanceContent( boost::shared_ptr< Core::Data::InstanceContent > pInstanceContent, + uint32_t guId, + const std::string& internalName, + const std::string& contentName, + uint32_t instanceContentId ); + virtual ~InstanceContent(); + + boost::shared_ptr< Core::Data::InstanceContent > getInstanceContentInfo() const; + + uint32_t getInstanceContentId() const; + +private: + Event::DirectorPtr m_pDirector; + boost::shared_ptr< Core::Data::InstanceContent > m_instanceContentInfo; + uint32_t m_instanceContentId; + InstanceContentState m_state; + +}; + +} +#endif //SAPPHIRE_INSTANCECONTENT_H diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp new file mode 100644 index 00000000..cb5c3209 --- /dev/null +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp @@ -0,0 +1,346 @@ +#include "TerritoryMgr.h" + +#include +#include +#include + +#include "Actor/Player.h" + +#include "Zone.h" +#include "ZonePosition.h" +#include "InstanceContent.h" + +extern Core::Logger g_log; +extern Core::Data::ExdData g_exdData; +extern Core::Data::ExdDataGenerated g_exdDataGen; + +Core::TerritoryMgr::TerritoryMgr() : + m_lastInstanceId( 10000 ) +{ + +} + +void Core::TerritoryMgr::loadTerritoryTypeDetailCache() +{ + auto idList = g_exdDataGen.getTerritoryTypeIdList(); + + for( auto id : idList ) + { + auto teri1 = g_exdDataGen.getTerritoryType( id ); + + if( !teri1->name.empty() ) + m_territoryTypeDetailCacheMap[id] = teri1; + } +} + +bool Core::TerritoryMgr::isValidTerritory( uint32_t territoryTypeId ) const +{ + return !( m_territoryTypeDetailCacheMap.find( territoryTypeId ) == m_territoryTypeDetailCacheMap.end() ); +} + +bool Core::TerritoryMgr::init() +{ + loadTerritoryTypeDetailCache(); + loadTerritoryPositionMap(); + + createDefaultTerritories(); + + return true; +} + +uint32_t Core::TerritoryMgr::getNextInstanceId() +{ + return ++m_lastInstanceId; +} + +Core::Data::TerritoryTypePtr Core::TerritoryMgr::getTerritoryDetail( uint32_t territoryTypeId ) const +{ + auto tIt = m_territoryTypeDetailCacheMap.find( territoryTypeId ); + if( tIt == m_territoryTypeDetailCacheMap.end() ) + return nullptr; + + return tIt->second; +} + +bool Core::TerritoryMgr::isInstanceContentTerritory( uint32_t territoryTypeId ) const +{ + auto pTeri = getTerritoryDetail( territoryTypeId ); + + if( !pTeri ) + return false; + + return pTeri->territoryIntendedUse == TerritoryIntendedUse::AllianceRaid || + pTeri->territoryIntendedUse == TerritoryIntendedUse::BeforeTrialDung || + pTeri->territoryIntendedUse == TerritoryIntendedUse::Trial || + pTeri->territoryIntendedUse == TerritoryIntendedUse::Dungeon || + pTeri->territoryIntendedUse == TerritoryIntendedUse::OpenWorldInstanceBattle || + pTeri->territoryIntendedUse == TerritoryIntendedUse::PalaceOfTheDead || + pTeri->territoryIntendedUse == TerritoryIntendedUse::RaidFights || + pTeri->territoryIntendedUse == TerritoryIntendedUse::Raids || + pTeri->territoryIntendedUse == TerritoryIntendedUse::TreasureMapInstance; +} + +bool Core::TerritoryMgr::isPrivateTerritory( uint32_t territoryTypeId ) const +{ + auto pTeri = getTerritoryDetail( territoryTypeId ); + + if( !pTeri ) + return false; + + return pTeri->territoryIntendedUse == TerritoryIntendedUse::OpeningArea || + pTeri->territoryIntendedUse == TerritoryIntendedUse::Inn || + pTeri->territoryIntendedUse == TerritoryIntendedUse::HousingPrivateArea || + pTeri->territoryIntendedUse == TerritoryIntendedUse::JailArea || + pTeri->territoryIntendedUse == TerritoryIntendedUse::MSQPrivateArea; +} + + +bool Core::TerritoryMgr::createDefaultTerritories() +{ + // for each entry in territoryTypeExd, check if it is a normal and if so, add the zone object + for( const auto& territory : m_territoryTypeDetailCacheMap ) + { + auto territoryId = territory.first; + auto territoryInfo = territory.second; + + // if the zone has no name set + if( territoryInfo->name.empty() ) + continue; + + auto pPlaceName = g_exdDataGen.getPlaceName( territoryInfo->placeName ); + + if( !pPlaceName || pPlaceName->name.empty() || !isDefaultTerritory( territoryId ) ) + continue; + + uint32_t guid = getNextInstanceId(); + g_log.Log( LoggingSeverity::info, std::to_string( territoryId ) + + "\t" + std::to_string( guid ) + + "\t" + std::to_string( territoryInfo->territoryIntendedUse ) + + "\t" + territoryInfo->name + + "\t" + pPlaceName->name ); + + ZonePtr pZone( new Zone( territoryId, guid, territoryInfo->name, pPlaceName->name ) ); + pZone->init(); + + InstanceIdToZonePtrMap instanceMap; + instanceMap[guid] = pZone; + m_instanceIdToZonePtrMap[guid] = pZone; + m_territoryInstanceMap[territoryId] = instanceMap; + + } + + return true; +} + +Core::ZonePtr Core::TerritoryMgr::createTerritoryInstance( uint32_t territoryTypeId ) +{ + if( !isValidTerritory( territoryTypeId ) ) + return nullptr; + + if( isInstanceContentTerritory( territoryTypeId ) ) + return nullptr; + + auto pTeri = getTerritoryDetail( territoryTypeId ); + auto pPlaceName = g_exdDataGen.getPlaceName( pTeri->placeName ); + + if( !pTeri || !pPlaceName ) + return nullptr; + + g_log.debug( "Starting instance for territory: " + std::to_string( territoryTypeId ) + " (" + pPlaceName->name + ")" ); + + ZonePtr pZone = ZonePtr( new Zone( territoryTypeId, getNextInstanceId(), pTeri->name, pPlaceName->name ) ); + pZone->init(); + + m_territoryInstanceMap[pZone->getTerritoryId()][pZone->getGuId()] = pZone; + m_instanceIdToZonePtrMap[pZone->getGuId()] = pZone; + + return pZone; +} + +Core::ZonePtr Core::TerritoryMgr::createInstanceContent( uint32_t instanceContentId ) +{ + auto pInstanceContent = g_exdDataGen.getInstanceContent( instanceContentId ); + if( !pInstanceContent ) + return nullptr; + + if( !isInstanceContentTerritory( pInstanceContent->territoryType ) ) + return nullptr; + + auto pTeri = getTerritoryDetail( pInstanceContent->territoryType ); + + if( !pTeri || pInstanceContent->name.empty() ) + return nullptr; + + g_log.debug( "Starting instance for InstanceContent id: " + std::to_string( instanceContentId ) + + " (" + pInstanceContent->name + ")" ); + + ZonePtr pZone = ZonePtr( new InstanceContent( pInstanceContent, getNextInstanceId(), pTeri->name, + pInstanceContent->name, instanceContentId ) ); + pZone->init(); + + m_instanceContentToInstanceMap[instanceContentId][pZone->getGuId()] = pZone; + m_instanceIdToZonePtrMap[pZone->getGuId()] = pZone; + + return pZone; +} + +bool Core::TerritoryMgr::removeTerritoryInstance( uint32_t instanceId ) +{ + ZonePtr pZone; + if( ( pZone = getInstanceZonePtr( instanceId ) ) == nullptr ) + return false; + + m_instanceIdToZonePtrMap.erase( pZone->getGuId() ); + + if( isInstanceContentTerritory( pZone->getTerritoryId() ) ) + { + auto instance = boost::dynamic_pointer_cast< InstanceContent >( pZone ); + m_instanceContentToInstanceMap[instance->getInstanceContentId()].erase( pZone->getGuId() ); + } + else + m_territoryInstanceMap[pZone->getTerritoryId()].erase( pZone->getGuId() ); + + + return true; +} + +Core::ZonePtr Core::TerritoryMgr::getInstanceZonePtr( uint32_t instanceId ) const +{ + auto it = m_instanceIdToZonePtrMap.find( instanceId ); + if( it == m_instanceIdToZonePtrMap.end() ) + return nullptr; + + return it->second; +} + +void Core::TerritoryMgr::loadTerritoryPositionMap() +{ + auto pQR = g_charaDb.query( "SELECT id, target_zone_id, pos_x, pos_y, pos_z, pos_o, radius FROM zonepositions;" ); + + 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] = ZonePositionPtr( new ZonePosition( id, targetZoneId, pos, radius, posO ) ); + } +} + +bool Core::TerritoryMgr::isDefaultTerritory( uint32_t territoryTypeId ) const +{ + 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; + +} + +Core::ZonePositionPtr Core::TerritoryMgr::getTerritoryPosition( uint32_t territoryPositionId ) const +{ + auto it = m_territoryPositionMap.find( territoryPositionId ); + + if( it != m_territoryPositionMap.end() ) + return it->second; + + return nullptr; +} + +Core::ZonePtr Core::TerritoryMgr::getZoneByTerriId( uint32_t territoryId ) const +{ + auto zoneMap = m_territoryInstanceMap.find( territoryId ); + if( zoneMap == m_territoryInstanceMap.end() ) + return nullptr; + + // TODO: actually select the proper one + return zoneMap->second.begin()->second; +} + +void Core::TerritoryMgr::updateTerritoryInstances( uint32_t currentTime ) +{ + for( auto zoneMap : m_territoryInstanceMap ) + { + for( auto zone : zoneMap.second ) + zone.second->runZoneLogic( currentTime ); + } + + for( auto zoneMap : m_instanceContentToInstanceMap ) + { + for( auto zone: zoneMap.second ) + zone.second->runZoneLogic( currentTime ); + } +} + +Core::TerritoryMgr::InstanceIdList Core::TerritoryMgr::getInstanceContentIdList( uint16_t instanceContentId ) const +{ + std::vector< uint32_t > idList; + auto zoneMap = m_instanceContentToInstanceMap.find( instanceContentId ); + if( zoneMap == m_instanceContentToInstanceMap.end() ) + return idList; + + for( auto& entry : zoneMap->second ) + { + idList.push_back( entry.first ); + } + + return idList; +} + +bool Core::TerritoryMgr::movePlayer( uint32_t territoryId, Core::Entity::PlayerPtr pPlayer ) +{ + auto pZone = getZoneByTerriId( territoryId ); + + if( !pZone ) + { + g_log.error( "Zone " + std::to_string( territoryId ) + " not found on this server." ); + return false; + } + + pPlayer->setTerritoryId( territoryId ); + + // mark character as zoning in progress + pPlayer->setLoadingComplete( false ); + + if( pPlayer->getLastPing() != 0 ) + pPlayer->getCurrentZone()->removeActor( pPlayer ); + + pPlayer->setCurrentZone( pZone ); + pZone->pushActor( pPlayer ); + + return true; +} + +bool Core::TerritoryMgr::movePlayer( ZonePtr pZone, Core::Entity::PlayerPtr pPlayer ) +{ + if( !pZone ) + { + g_log.error( "Zone not found on this server." ); + return false; + } + + pPlayer->setTerritoryId( pZone->getTerritoryId() ); + + // mark character as zoning in progress + pPlayer->setLoadingComplete( false ); + + if( pPlayer->getLastPing() != 0 ) + pPlayer->getCurrentZone()->removeActor( pPlayer ); + + pPlayer->setCurrentZone( pZone ); + pZone->pushActor( pPlayer ); + + return true; +} + + + diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.h b/src/servers/sapphire_zone/Zone/TerritoryMgr.h new file mode 100644 index 00000000..24318550 --- /dev/null +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.h @@ -0,0 +1,150 @@ +#ifndef SAPPHIRE_TERRITORYMGR_H +#define SAPPHIRE_TERRITORYMGR_H + +#include +#include "Forwards.h" + +namespace Core +{ + namespace Data + { + // TODO: this should actually not be here but should be generated in exdData aswell + struct PlaceName; + struct TerritoryType; + struct InstanceContent; + + using PlaceNamePtr = boost::shared_ptr< PlaceName >; + using TerritoryTypePtr = boost::shared_ptr< TerritoryType >; + using InstanceContentPtr = boost::shared_ptr< InstanceContent >; + } + + /*! + \class TerritoryMgr_c + \brief A class managing zones + + This class manages persistent and temporary instances alike. + + */ + class TerritoryMgr + { + + public: + enum TerritoryIntendedUse : uint8_t //ToDo: Add The Rest of The Territory Types and Have Better Names For Them + { + Town = 0, + OpenWorld = 1, + Inn = 2, + Dungeon = 3, + JailArea = 5, + OpeningArea = 6, + BeforeTrialDung = 7, + AllianceRaid = 8, + OpenWorldInstanceBattle = 9, + Trial = 10, + HousingArea = 13, + HousingPrivateArea = 14, + MSQPrivateArea = 15, + Raids = 16, + RaidFights = 17, + ChocoboTutorial = 21, + Wedding = 22, + BeginnerTutorial = 27, + FreeCompanyGarrison = 30, + PalaceOfTheDead = 31, + TreasureMapInstance = 33, + EventArea = 40, + }; + + TerritoryMgr(); + + /*! initializes the territoryMgr */ + bool init(); + + bool createDefaultTerritories(); + + /*! caches TerritoryType details into m_territoryTypeMap */ + void loadTerritoryTypeDetailCache(); + + /*! List of positions for zonelines */ + void loadTerritoryPositionMap(); + + /*! returns true if the given territoryTypeId is in fact a valid zone + based on informations in the dats ( checks if an entry in the dats exists trhough cache ) */ + bool isValidTerritory( uint32_t territoryTypeId ) const; + + /*! returns the next available instanceId */ + uint32_t getNextInstanceId(); + + /*! returns true if the territoryType in question is not a persistant zone */ + bool isInstanceContentTerritory( uint32_t territoryTypeId ) const; + + /*! returns true if the territoryType in question is not a private zone */ + bool isPrivateTerritory( uint32_t territoryTypeId ) const; + + /*! returns true if the territoryType is a default non-instanced zone */ + bool isDefaultTerritory( uint32_t territoryTypeId ) const; + + /*! creates a new instance for a given territoryTypeId */ + ZonePtr createTerritoryInstance( uint32_t territoryTypeId ); + + ZonePtr createInstanceContent( uint32_t instanceContentId ); + + /*! removes instance by instanceId, return true if successful */ + bool removeTerritoryInstance( uint32_t territoryTypeId ); + + /*! returns a ZonePtr to the instance or nullptr if not found */ + ZonePtr getInstanceZonePtr( uint32_t instanceId ) const; + + /*! returns the cached detail of a territory, nullptr if not found */ + Data::TerritoryTypePtr getTerritoryDetail( uint32_t territoryTypeId ) const; + + /*! loop for processing territory logic, iterating all existing instances */ + void updateTerritoryInstances( uint32_t currentTime ); + + /*! returns a ZonePositionPtr if found, else nullptr */ + ZonePositionPtr getTerritoryPosition( uint32_t territoryPositionId ) const; + + /*! returns a default Zone by territoryId + TODO: Mind multiple instances?! */ + ZonePtr getZoneByTerriId( uint32_t territoryId ) const; + + + bool movePlayer( uint32_t territoryId, Entity::PlayerPtr pPlayer ); + bool movePlayer( ZonePtr, Entity::PlayerPtr pPlayer ); + + private: + using TerritoryTypeDetailCache = std::unordered_map< uint16_t, Data::TerritoryTypePtr >; + using InstanceIdToZonePtrMap = std::unordered_map< uint32_t, ZonePtr >; + using TerritoryIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToZonePtrMap >; + using InstanceContentIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToZonePtrMap >; + using PlayerIdToInstanceIdMap = std::unordered_map< uint32_t, uint32_t >; + using PositionMap = std::unordered_map< int32_t, ZonePositionPtr >; + using InstanceIdList = std::vector< uint32_t >; + + /*! map holding details for territory templates */ + TerritoryTypeDetailCache m_territoryTypeDetailCacheMap; + + /*! map holding actual instances of default territories */ + TerritoryIdToInstanceMap m_territoryInstanceMap; + + /*! map holding actual instances of InstanceContent */ + InstanceContentIdToInstanceMap m_instanceContentToInstanceMap; + + /*! flat map for easier lookup of instances by guid */ + InstanceIdToZonePtrMap m_instanceIdToZonePtrMap; + + /*! map holding positions for zonelines */ + PositionMap m_territoryPositionMap; + + /*! internal counter for instanceIds */ + uint32_t m_lastInstanceId; + + public: + /*! returns a list of instanceContent InstanceIds currently active */ + InstanceIdList getInstanceContentIdList( uint16_t instanceContentId ) const; + + }; + +} + +#endif // SAPPHIRE_TERRITORYMGR_H diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index 3b0fe8e0..c2141e68 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -13,7 +13,7 @@ #include #include "Zone.h" -#include "ZoneMgr.h" +#include "TerritoryMgr.h" #include "Session.h" #include "Actor/Actor.h" @@ -42,9 +42,8 @@ namespace Core { * \brief */ Zone::Zone() - : m_zoneId( 0 ) - , m_layoutId( 0 ) - , m_bPrivate( false ) + : m_territoryId( 0 ) + , m_guId( 0 ) , m_type( Common::RegionType::normal ) , m_currentWeather( static_cast< uint8_t >( Common::Weather::FairSkies ) ) , m_weatherOverride( 0 ) @@ -52,16 +51,15 @@ Zone::Zone() { } -Zone::Zone( uint16_t zoneId, uint32_t layoutId, std::string name, std::string interName, bool bPrivate = false ) +Zone::Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName, const std::string& placeName ) : m_type( Common::RegionType::normal ) , m_currentWeather( static_cast< uint8_t >( Common::Weather::FairSkies ) ) { - m_layoutId = layoutId; + m_guId = guId; - m_zoneId = zoneId; - m_zoneCode = name; - m_zoneName = interName; - m_bPrivate = bPrivate; + m_territoryId = territoryId; + m_internalName = internalName; + m_placeName = placeName; m_lastMobUpdate = 0; m_currentWeather = getNextWeather(); @@ -151,7 +149,7 @@ void Zone::loadCellCache() "Look," "Models," "type " - "FROM battlenpc WHERE ZoneId = " + std::to_string( getId() ) + ";" ); + "FROM battlenpc WHERE ZoneId = " + std::to_string(getTerritoryId() ) + ";" ); std::vector< Entity::BattleNpcPtr > cache; @@ -176,10 +174,7 @@ void Zone::loadCellCache() uint32_t modelId = pQR->getUInt( 17 ); uint32_t type = pQR->getUInt( 18 ); - Common::FFXIVARR_POSITION3 pos; - pos.x = posX; - pos.y = posY; - pos.z = posZ; + Common::FFXIVARR_POSITION3 pos{ posX, posY, posZ }; Entity::BattleNpcPtr pBNpc( new Entity::BattleNpc( modelId, nameId, pos, sizeId, type, level, behaviour, mobType ) ); pBNpc->setRotation( static_cast< float >( rotation ) ); @@ -191,8 +186,8 @@ void Zone::loadCellCache() for( auto entry : cache ) { // get cell position - uint32_t cellX = CellHandler< ZoneMgr >::getPosX( entry->getPos().x ); - uint32_t cellY = CellHandler< ZoneMgr >::getPosY( entry->getPos().z ); + uint32_t cellX = CellHandler< TerritoryMgr >::getPosX( entry->getPos().x ); + uint32_t cellY = CellHandler< TerritoryMgr >::getPosY( entry->getPos().z ); // find the right cell, create it if not existing yet if( m_pCellCache[cellX] == nullptr ) @@ -212,9 +207,9 @@ void Zone::loadCellCache() uint8_t Zone::getNextWeather() { - auto zoneInfo = g_exdData.m_zoneInfoMap[ getLayoutId() ]; + auto zoneInfo = g_exdData.m_zoneInfoMap[getTerritoryId()]; - uint32_t unixTime = static_cast< uint32_t >( time( nullptr ) ); + uint32_t unixTime = static_cast< uint32_t >( Util::getTimeSeconds() ); // Get Eorzea hour for weather start uint32_t bell = unixTime / 175; // Do the magic 'cause for calculations 16:00 is 0, 00:00 is 8 and 08:00 is 16 @@ -228,12 +223,12 @@ uint8_t Zone::getNextWeather() uint32_t step1 = ( calcBase << 0xB ) ^ calcBase; uint32_t step2 = ( step1 >> 8 ) ^ step1; - uint8_t rate = static_cast< uint8_t >(step2 % 0x64); + auto rate = static_cast< uint8_t >( step2 % 0x64 ); for( auto entry : zoneInfo.weather_rate_map ) { uint8_t sRate = entry.first; - int32_t weatherId = entry.second; + auto weatherId = static_cast< uint8_t >( entry.second ); if( rate <= sRate ) return weatherId; @@ -281,7 +276,7 @@ void Zone::pushActor( Entity::ActorPtr pActor ) if( pActor->isPlayer() ) { - g_log.debug( "[Zone:" + m_zoneCode + "] Adding player [" + std::to_string( pActor->getId() ) + "]" ); + g_log.debug( "[Zone:" + m_internalName + "] Adding player [" + std::to_string( pActor->getId() ) + "]" ); auto pPlayer = pActor->getAsPlayer(); auto pSession = g_serverZone.getSession( pPlayer->getId() ); @@ -320,7 +315,7 @@ void Zone::removeActor( Entity::ActorPtr pActor ) if( pActor->isPlayer() ) { - g_log.debug( "[Zone:" + m_zoneCode + "] Removing player [" + std::to_string( pActor->getId() ) + "]" ); + g_log.debug( "[Zone:" + m_internalName + "] Removing player [" + std::to_string( pActor->getId() ) + "]" ); // If it's a player and he's inside boundaries - update his nearby cells if( pActor->getPos().x <= _maxX && pActor->getPos().x >= _minX && pActor->getPos().z <= _maxY && pActor->getPos().z >= _minY ) @@ -372,9 +367,9 @@ void Zone::queueOutPacketForRange( Entity::Player& sourcePlayer, uint32_t range, } } -uint32_t Zone::getId() +uint32_t Zone::getTerritoryId() { - return m_zoneId; + return m_territoryId; } Common::RegionType Zone::getType() const @@ -382,9 +377,9 @@ Common::RegionType Zone::getType() const return m_type; } -uint16_t Zone::getLayoutId() const +uint16_t Zone::getGuId() const { - return m_layoutId; + return m_guId; } bool Zone::isInstance() const @@ -394,12 +389,12 @@ bool Zone::isInstance() const const std::string& Zone::getName() const { - return m_zoneName; + return m_placeName; } const std::string& Zone::getInternalName() const { - return m_zoneCode; + return m_internalName; } std::size_t Zone::getPopCount() const @@ -414,7 +409,7 @@ bool Zone::checkWeather() if ( m_weatherOverride != m_currentWeather ) { m_currentWeather = m_weatherOverride; - g_log.debug( "[Zone:" + m_zoneCode + "] overriding weather to : " + std::to_string( m_weatherOverride ) ); + g_log.debug( "[Zone:" + m_internalName + "] overriding weather to : " + std::to_string( m_weatherOverride ) ); return true; } } @@ -424,7 +419,7 @@ bool Zone::checkWeather() if ( nextWeather != m_currentWeather ) { m_currentWeather = nextWeather; - g_log.debug( "[Zone:" + m_zoneCode + "] changing weather to : " + std::to_string( nextWeather ) ); + g_log.debug( "[Zone:" + m_internalName + "] changing weather to : " + std::to_string( nextWeather ) ); return true; } } @@ -462,7 +457,7 @@ void Zone::updateBnpcs( int64_t tickCount ) for( auto entry : m_BattleNpcMap ) { Entity::BattleNpcPtr pBNpc = entry.second; - + if( !pBNpc ) continue; @@ -472,27 +467,27 @@ void Zone::updateBnpcs( int64_t tickCount ) m_BattleNpcDeadMap.insert( pBNpc ); break; } - + pBNpc->update( tickCount ); } } } -bool Zone::runZoneLogic() +bool Zone::runZoneLogic( uint32_t currTime ) { int64_t tickCount = Util::getTimeMs(); bool changedWeather = checkWeather(); auto it = m_sessionSet.begin(); - + // update sessions in this zone for( ; it != m_sessionSet.end(); ) { auto pSession = ( *it ); - + if( !pSession ) { it = m_sessionSet.erase( it ); @@ -502,7 +497,7 @@ bool Zone::runZoneLogic() // this session is not linked to this area anymore, remove it from zone session list if( ( !pSession->getPlayer()->getCurrentZone() ) || ( pSession->getPlayer()->getCurrentZone() != shared_from_this() ) ) { - g_log.debug( "[Zone:" + m_zoneCode + "] removing session " + std::to_string( pSession->getId() ) ); + g_log.debug( "[Zone:" + m_internalName + "] removing session " + std::to_string( pSession->getId() ) ); if( pSession->getPlayer()->getCell() ) removeActor( pSession->getPlayer() ); @@ -641,8 +636,8 @@ void Zone::changeActorPosition( Entity::ActorPtr pActor ) pActor->removeInRangeActor( *iter2 ); - // @TODO FIXME! - // this break is more or less a hack, iteration will break otherwise after removing + // @TODO FIXME! + // this break is more or less a hack, iteration will break otherwise after removing break; } } diff --git a/src/servers/sapphire_zone/Zone/Zone.h b/src/servers/sapphire_zone/Zone/Zone.h index 4521373d..2c1fe699 100644 --- a/src/servers/sapphire_zone/Zone/Zone.h +++ b/src/servers/sapphire_zone/Zone/Zone.h @@ -15,26 +15,21 @@ #include #include namespace Core { -namespace Entity -{ - class Actor; - class Player; -} class Session; class ZonePosition; -typedef std::set< SessionPtr > SessionSet; +using SessionSet = std::set< SessionPtr >; class Zone : public CellHandler< Cell >, public boost::enable_shared_from_this< Zone > { protected: - uint32_t m_zoneId; - uint32_t m_layoutId; + uint32_t m_territoryId; + uint32_t m_guId; - std::string m_zoneName; - std::string m_zoneCode; + std::string m_placeName; + std::string m_internalName; bool m_bPrivate; @@ -58,7 +53,7 @@ protected: public: Zone(); - Zone( uint16_t zoneId, uint32_t layoutId, std::string name, std::string interName, bool bPrivate ); + Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName, const std::string& placeName ); virtual ~Zone(); bool init(); @@ -92,11 +87,11 @@ public: void queueOutPacketForRange( Entity::Player& sourcePlayer, uint32_t range, Network::Packets::GamePacketPtr pPacketEntry ); - virtual uint32_t getId(); + virtual uint32_t getTerritoryId(); Common::RegionType getType() const; - uint16_t getLayoutId() const; + uint16_t getGuId() const; bool isInstance() const; @@ -108,7 +103,7 @@ public: bool checkWeather(); void updateBnpcs( int64_t tickCount ); - bool runZoneLogic(); + bool runZoneLogic( uint32_t currTime ); }; diff --git a/src/servers/sapphire_zone/Zone/ZoneMgr.cpp b/src/servers/sapphire_zone/Zone/ZoneMgr.cpp deleted file mode 100644 index e644f4b5..00000000 --- a/src/servers/sapphire_zone/Zone/ZoneMgr.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include - -#include "ZoneMgr.h" -#include "Zone.h" -#include "ZonePosition.h" - - -extern Core::Logger g_log; -extern Core::Data::ExdData g_exdData; - -namespace Core { - - ZoneMgr::ZoneMgr() = default; - - ZoneMgr::~ZoneMgr() = default; - - void ZoneMgr::loadZonePositionMap() - { - auto pQR = g_charaDb.query( "SELECT id, target_zone_id, pos_x, pos_y, pos_z, pos_o, radius FROM zonepositions;" ); - - 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_zonePositionMap[id] = ZonePositionPtr( new ZonePosition( id, targetZoneId, pos, radius, posO ) ); - } - } - - ZonePositionPtr ZoneMgr::getZonePosition( uint32_t zonePositionId ) - { - auto it = m_zonePositionMap.find( zonePositionId ); - - if( it != m_zonePositionMap.end() ) - return it->second; - - return nullptr; - } - - bool ZoneMgr::createZones() - { - loadZonePositionMap(); - - // find zone info from exd - for( auto zone : g_exdData.m_zoneInfoMap ) - { - uint32_t zoneId = zone.first; - - - auto info = zone.second; - g_log.Log( LoggingSeverity::info, std::to_string( info.id ) + "\t" + info.zone_str ); - - ZonePtr pZone( new Zone( info.id, info.layout_id, info.zone_name, info.zone_str, false ) ); - pZone->init(); - m_zoneMap[info.id] = pZone; - } - - return true; - } - - void ZoneMgr::updateZones() - { - for( auto zone : m_zoneMap ) - { - zone.second->runZoneLogic(); - } - } - - ZonePtr ZoneMgr::getZone( uint32_t zoneId ) - { - ZoneMap::iterator it; - it = m_zoneMap.find( zoneId ); - - if( it != m_zoneMap.end() ) - return it->second; - - return nullptr; - } - -} diff --git a/src/servers/sapphire_zone/Zone/ZoneMgr.h b/src/servers/sapphire_zone/Zone/ZoneMgr.h deleted file mode 100644 index bab6c23b..00000000 --- a/src/servers/sapphire_zone/Zone/ZoneMgr.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _ZONEMGR_H -#define _ZONEMGR_H - - -#include -#include -#include "Forwards.h" - -namespace Core { - - using ZoneMap = std::unordered_map< uint32_t, ZonePtr >; - - class ZoneMgr - { - public: - ZoneMgr(); - ~ZoneMgr(); - - bool createZones(); - - ZonePtr getZone( uint32_t zoneId ); - - void loadZonePositionMap(); - - ZonePositionPtr getZonePosition( uint32_t zonePositionId ); - - void updateZones(); - - private: - ZoneMap m_zoneMap; - - std::unordered_map m_zonePositionMap; - - }; - -} - -#endif - diff --git a/src/tools/exd_struct_test/main.cpp b/src/tools/exd_struct_test/main.cpp index a3b50104..0b9e66cc 100644 --- a/src/tools/exd_struct_test/main.cpp +++ b/src/tools/exd_struct_test/main.cpp @@ -9,7 +9,7 @@ #include #include #include -#include "ExdDataGenerated.h" +#include #include #include #include