From 416366c144095886daba0775de1dadf866fd8222 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 28 Feb 2018 22:25:11 +1100 Subject: [PATCH 1/4] director sequence/branch setters & debug command --- .../DebugCommand/DebugCommandHandler.cpp | 32 ++++++++++++++++--- src/servers/sapphire_zone/Event/Director.cpp | 10 ++++++ src/servers/sapphire_zone/Event/Director.h | 3 ++ .../sapphire_zone/Zone/InstanceContent.cpp | 20 ++++++++++++ .../sapphire_zone/Zone/InstanceContent.h | 2 ++ 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp index 72c31d5c..35e711cd 100644 --- a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp @@ -709,15 +709,13 @@ void Core::DebugCommandHandler::instance( char* data, Entity::Player &player, bo } else if( subCommand == "set" ) { - uint32_t instanceId; uint32_t index; uint32_t value; - sscanf( params.c_str(), "%d %d %d", &instanceId, &index, &value ); + sscanf( params.c_str(), "%d %d", &index, &value ); - auto pInstance = g_territoryMgr.getInstanceZonePtr( instanceId ); - if( !pInstance ) + auto instance = boost::dynamic_pointer_cast< InstanceContent >( player.getCurrentZone() ); + if( !instance ) return; - auto instance = boost::dynamic_pointer_cast< InstanceContent >( pInstance ); instance->setVar( static_cast< uint8_t >( index ), static_cast< uint8_t >( value ) ); } @@ -738,6 +736,30 @@ void Core::DebugCommandHandler::instance( char* data, Entity::Player &player, bo obj->setState( state ); } + else if( subCommand == "seq" ) + { + uint8_t seq; + + sscanf( params.c_str(), "%hhu", &seq ); + + auto instance = boost::dynamic_pointer_cast< InstanceContent >( player.getCurrentZone() ); + if( !instance ) + return; + + instance->setSequence( seq ); + } + else if( subCommand == "branch" ) + { + uint8_t branch; + + sscanf( params.c_str(), "%hhu", &branch ); + + auto instance = boost::dynamic_pointer_cast< InstanceContent >( player.getCurrentZone() ); + if( !instance ) + return; + + instance->setBranch( branch ); + } else if( subCommand == "festival" ) { uint32_t festivalId; diff --git a/src/servers/sapphire_zone/Event/Director.cpp b/src/servers/sapphire_zone/Event/Director.cpp index a201a5ab..9dee7702 100644 --- a/src/servers/sapphire_zone/Event/Director.cpp +++ b/src/servers/sapphire_zone/Event/Director.cpp @@ -168,3 +168,13 @@ void Core::Event::Director::setDirectorUI8JH( uint8_t value ) { m_unionData.ui8lh.UI8JH = value; } + +void Core::Event::Director::setDirectorBranch( uint8_t value ) +{ + m_branch = value; +} + +void Core::Event::Director::setDirectorSequence( uint8_t value ) +{ + m_sequence = value; +} diff --git a/src/servers/sapphire_zone/Event/Director.h b/src/servers/sapphire_zone/Event/Director.h index f5840390..1693d47b 100644 --- a/src/servers/sapphire_zone/Event/Director.h +++ b/src/servers/sapphire_zone/Event/Director.h @@ -72,6 +72,9 @@ public: void setDirectorUI8JL( uint8_t value ); void setDirectorUI8JH( uint8_t value ); + void setDirectorSequence( uint8_t value ); + void setDirectorBranch( uint8_t value ); + private: /*! Id of the content of the director */ uint16_t m_contentId; diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.cpp b/src/servers/sapphire_zone/Zone/InstanceContent.cpp index 201ac523..92910575 100644 --- a/src/servers/sapphire_zone/Zone/InstanceContent.cpp +++ b/src/servers/sapphire_zone/Zone/InstanceContent.cpp @@ -227,6 +227,26 @@ void Core::InstanceContent::setVar( uint8_t index, uint8_t value ) } } +void Core::InstanceContent::setSequence( uint8_t value ) +{ + setDirectorSequence( value ); + + for( const auto &playerIt : m_playerMap ) + { + sendDirectorVars( *playerIt.second ); + } +} + +void Core::InstanceContent::setBranch( uint8_t value ) +{ + setDirectorBranch( value ); + + for( const auto &playerIt : m_playerMap ) + { + sendDirectorVars( *playerIt.second ); + } +} + void Core::InstanceContent::onRegisterEObj( Entity::EventObjectPtr object ) { if( object->getName() != "none" ) diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.h b/src/servers/sapphire_zone/Zone/InstanceContent.h index 9dcb5974..e2aeb8ad 100644 --- a/src/servers/sapphire_zone/Zone/InstanceContent.h +++ b/src/servers/sapphire_zone/Zone/InstanceContent.h @@ -41,6 +41,8 @@ public: void onRegisterEObj( Entity::EventObjectPtr object ) override; void setVar( uint8_t index, uint8_t value ); + void setSequence( uint8_t value ); + void setBranch( uint8_t value ); boost::shared_ptr< Core::Data::InstanceContent > getInstanceContentInfo() const; From 521c62013c3a7e5d39e12f6f4fb264f830f09c6b Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 28 Feb 2018 22:25:34 +1100 Subject: [PATCH 2/4] ignore cotire generated files --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 00f3f1c8..400a9aba 100644 --- a/.gitignore +++ b/.gitignore @@ -113,4 +113,8 @@ src/common/Version\.cpp .mtime_cache # generated script loader files -src/servers/sapphire_zone/Script/Scripts/*/ScriptLoader.cpp \ No newline at end of file +src/servers/sapphire_zone/Script/Scripts/*/ScriptLoader.cpp + +# cotire generated files/folders +cotire/ +*_cotire.cmake \ No newline at end of file From d024f0a39665a945eeb1fef62d17b2231b21020d Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 28 Feb 2018 23:53:20 +1100 Subject: [PATCH 3/4] fix eobj out of bounds allocation client crash --- src/common/Common.h | 1 + .../Network/PacketDef/Zone/ServerZoneDef.h | 2 +- .../sapphire_zone/Actor/EventObject.cpp | 4 ++- src/servers/sapphire_zone/Actor/Player.cpp | 32 +++++++++++++++++-- src/servers/sapphire_zone/Actor/Player.h | 9 +++++- .../sapphire_zone/Zone/InstanceContent.cpp | 3 ++ 6 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index 6d5b204d..05517df7 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -16,6 +16,7 @@ namespace Common { // 99 is the last spawn id that seems to spawn any actor const uint8_t MAX_DISPLAYED_ACTORS = 99; + const uint8_t MAX_DISPLAYED_EOBJS = 40; const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000; diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 985af408..8684985d 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1316,7 +1316,7 @@ struct FFXIVIpcMSQTrackerComplete : FFXIVIpcBasePacket struct FFXIVIpcObjectSpawn : FFXIVIpcBasePacket { - uint8_t count; + uint8_t spawnIndex; uint8_t objKind; uint8_t state; uint8_t unknown3; diff --git a/src/servers/sapphire_zone/Actor/EventObject.cpp b/src/servers/sapphire_zone/Actor/EventObject.cpp index e624c124..4592fad5 100644 --- a/src/servers/sapphire_zone/Actor/EventObject.cpp +++ b/src/servers/sapphire_zone/Actor/EventObject.cpp @@ -100,7 +100,7 @@ void Core::Entity::EventObject::spawn( Core::Entity::PlayerPtr pTarget ) { g_log.debug( "Spawning EObj: id:" + std::to_string( getId() ) + " name:" + getName() ); ZoneChannelPacket< FFXIVIpcObjectSpawn > eobjStatePacket( getId(), pTarget->getId() ); - eobjStatePacket.data().count = pTarget->getNextObjCount(); + eobjStatePacket.data().spawnIndex = pTarget->getNextObjSpawnIndexForActorId( getId( )); eobjStatePacket.data().objKind = getObjKind(); eobjStatePacket.data().state = getState(); eobjStatePacket.data().objId = getObjectId(); @@ -115,6 +115,8 @@ void Core::Entity::EventObject::spawn( Core::Entity::PlayerPtr pTarget ) void Core::Entity::EventObject::despawn( Core::Entity::PlayerPtr pTarget ) { g_log.debug( "despawn eobj: " + std::to_string( getId() ) ); + + pTarget->freeObjSpawnIndexForActorId( getId( )); } const std::string& Core::Entity::EventObject::getName() const diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 65ab2fe5..f3f3b68a 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -1659,9 +1659,37 @@ void Core::Entity::Player::teleportQuery( uint16_t aetheryteId ) } } -uint8_t Core::Entity::Player::getNextObjCount() +uint8_t Core::Entity::Player::getNextObjSpawnIndexForActorId( uint32_t actorId ) { - return m_objCount++; + auto nextCount = m_freeObjCounts.front(); + m_freeObjCounts.pop(); + + m_actorIdToObjCountMap[actorId] = nextCount; + + return nextCount; +} + +void Core::Entity::Player::resetObjSpawnIndex() +{ + while( m_freeObjCounts.empty() ) + m_freeObjCounts.pop(); + + for( uint32_t i = 0; i < MAX_DISPLAYED_EOBJS; ++i ) + m_freeObjCounts.push( i ); + + m_actorIdToObjCountMap.clear(); +} + +void Core::Entity::Player::freeObjSpawnIndexForActorId( uint32_t actorId ) +{ + auto it = m_actorIdToObjCountMap.find( actorId ); + if( it == m_actorIdToObjCountMap.end() ) + return; + + auto freeCount = m_actorIdToObjCountMap[actorId]; + m_freeObjCounts.push( freeCount ); + + m_actorIdToObjCountMap.erase( actorId ); } void Core::Entity::Player::setOnEnterEventDone( bool isDone ) diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index 7f362e6a..877de137 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -562,7 +562,12 @@ public: void setOnEnterEventDone( bool isDone ); bool isOnEnterEventDone() const; - uint8_t getNextObjCount(); + /*! gets the next available obj count */ + uint8_t getNextObjSpawnIndexForActorId( uint32_t actorId ); + /*! resets the players obj count */ + void resetObjSpawnIndex(); + /*! frees an obj count to be used by another eobj */ + void freeObjSpawnIndexForActorId( uint32_t actorId ); private: uint32_t m_lastWrite; @@ -679,6 +684,8 @@ private: // counter used to index objects spawned for the player uint8_t m_objCount; + std::queue< uint8_t > m_freeObjCounts; + std::map< uint32_t, uint8_t > m_actorIdToObjCountMap; }; } diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.cpp b/src/servers/sapphire_zone/Zone/InstanceContent.cpp index 92910575..58a6fa7c 100644 --- a/src/servers/sapphire_zone/Zone/InstanceContent.cpp +++ b/src/servers/sapphire_zone/Zone/InstanceContent.cpp @@ -221,6 +221,7 @@ void Core::InstanceContent::setVar( uint8_t index, uint8_t value ) } + // todo: genericise this? for( const auto &playerIt : m_playerMap ) { sendDirectorVars( *playerIt.second ); @@ -274,6 +275,8 @@ void Core::InstanceContent::onBeforeEnterTerritory( Core::Entity::Player &player player.setRot( PI ); player.setPos( { 0.f, 0.f, 0.f } ); } + + player.resetObjSpawnIndex( ); } Core::Entity::EventObjectPtr Core::InstanceContent::getEObjByName( const std::string &name ) From af8cfeeb58f4d5c26d8ea0e502bc7cca51b58559 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 28 Feb 2018 23:58:11 +1100 Subject: [PATCH 4/4] note to self --- src/servers/sapphire_zone/Actor/Player.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index f3f3b68a..a5afe5b3 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -1661,6 +1661,7 @@ void Core::Entity::Player::teleportQuery( uint16_t aetheryteId ) uint8_t Core::Entity::Player::getNextObjSpawnIndexForActorId( uint32_t actorId ) { + // todo: fix it so the case where there's no ids available doesn't break everything :( auto nextCount = m_freeObjCounts.front(); m_freeObjCounts.pop();