From 3cf460cc5233d6201202a8a9c17d082c103a6b7c Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Mon, 31 Jul 2023 02:13:19 -0700 Subject: [PATCH] throw away the old impl --- dCommon/dEnums/eMovementPlatformState.h | 14 +- dGame/dComponents/MovingPlatformComponent.cpp | 416 ++++++++---------- dGame/dComponents/MovingPlatformComponent.h | 157 +++---- dGame/dGameMessages/GameMessages.cpp | 2 +- dGame/dGameMessages/GameMessages.h | 2 +- .../Map/General/PropertyPlatform.cpp | 13 +- dScripts/ai/AG/AgQbElevator.cpp | 6 +- .../dComponentsTests/CMakeLists.txt | 1 + .../MovingPlatformComponentTests.cpp | 158 +++++++ 9 files changed, 442 insertions(+), 327 deletions(-) create mode 100644 tests/dGameTests/dComponentsTests/MovingPlatformComponentTests.cpp diff --git a/dCommon/dEnums/eMovementPlatformState.h b/dCommon/dEnums/eMovementPlatformState.h index 1df437d8..dc7a85cd 100644 --- a/dCommon/dEnums/eMovementPlatformState.h +++ b/dCommon/dEnums/eMovementPlatformState.h @@ -4,13 +4,19 @@ #include /** - * The different types of platform movement state, supposedly a bitmap + * The different types of platform movement state */ enum class eMovementPlatformState : uint32_t { - Moving = 0b00010, - Stationary = 0b11001, - Stopped = 0b01100 + Waiting = 1 << 0U, + Travelling = 1 << 1U, + Stopped = 1 << 2U, + ReachedDesiredWaypoint = 1 << 3U, + ReachedFinalWaypoint = 1 << 4U, +}; + +inline constexpr eMovementPlatformState operator|(eMovementPlatformState a, eMovementPlatformState b) { + return static_cast(static_cast(a) | static_cast(b)); }; #endif //!__EMOVEMENTPLATFORMSTATE__H__ diff --git a/dGame/dComponents/MovingPlatformComponent.cpp b/dGame/dComponents/MovingPlatformComponent.cpp index f4dcdbe9..75817056 100644 --- a/dGame/dComponents/MovingPlatformComponent.cpp +++ b/dGame/dComponents/MovingPlatformComponent.cpp @@ -14,107 +14,84 @@ #include "SimplePhysicsComponent.h" #include "Zone.h" -MoverSubComponent::MoverSubComponent(const NiPoint3& startPos) { - mPosition = {}; +PlatformSubComponent::PlatformSubComponent() { + m_Position = NiPoint3::ZERO; - mState = eMovementPlatformState::Stopped; - mDesiredWaypointIndex = 0; // -1; - mInReverse = false; - mShouldStopAtDesiredWaypoint = false; + m_State = eMovementPlatformState::Stopped | eMovementPlatformState::ReachedDesiredWaypoint; + m_DesiredWaypointIndex = 0; + m_InReverse = false; + m_ShouldStopAtDesiredWaypoint = false; - mPercentBetweenPoints = 0.0f; + m_PercentBetweenPoints = 0.0f; - mCurrentWaypointIndex = 0; - mNextWaypointIndex = 0; //mCurrentWaypointIndex + 1; + m_CurrentWaypointIndex = 0; + m_NextWaypointIndex = 0; - mIdleTimeElapsed = 0.0f; + m_IdleTimeElapsed = 0.0f; } -MoverSubComponent::~MoverSubComponent() = default; - -void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const { - outBitStream->Write(true); - - outBitStream->Write(static_cast(mState)); - outBitStream->Write(mDesiredWaypointIndex); - outBitStream->Write(mShouldStopAtDesiredWaypoint); - outBitStream->Write(mInReverse); - - outBitStream->Write(mPercentBetweenPoints); - - outBitStream->Write(mPosition.x); - outBitStream->Write(mPosition.y); - outBitStream->Write(mPosition.z); - - outBitStream->Write(mCurrentWaypointIndex); - outBitStream->Write(mNextWaypointIndex); - - outBitStream->Write(mIdleTimeElapsed); - outBitStream->Write(0.0f); // Move time elapsed +void PlatformSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { + outBitStream->Write(m_IsDirty); + if (!m_IsDirty) return; + outBitStream->Write(m_State); + outBitStream->Write(m_DesiredWaypointIndex); + outBitStream->Write(m_ShouldStopAtDesiredWaypoint); + outBitStream->Write(m_InReverse); + outBitStream->Write(m_PercentBetweenPoints); + outBitStream->Write(m_Position.x); + outBitStream->Write(m_Position.y); + outBitStream->Write(m_Position.z); + outBitStream->Write(m_CurrentWaypointIndex); + outBitStream->Write(m_NextWaypointIndex); + outBitStream->Write(m_IdleTimeElapsed); + outBitStream->Write(m_MoveTimeElapsed); + if (!bIsInitialUpdate) m_IsDirty = false; } //------------- MovingPlatformComponent below -------------- MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::string& pathName) : Component(parent) { - m_MoverSubComponentType = eMoverSubComponentType::mover; - m_MoverSubComponent = new MoverSubComponent(m_Parent->GetDefaultPosition()); - m_PathName = GeneralUtils::ASCIIToUTF16(pathName); - m_Path = Game::zoneManager->GetZone()->GetPath(pathName); - m_NoAutoStart = false; + if (Game::zoneManager == nullptr) return; + auto path = Game::zoneManager->GetZone()->GetPath(pathName); + if (!path) return; + Game::logger->Log("MovingPlatformComponent", "Path found: %s", pathName.c_str()); - if (m_Path == nullptr) { - Game::logger->Log("MovingPlatformComponent", "Path not found: %s", pathName.c_str()); + if (m_Parent->GetVar(u"platformIsSimpleMover")) { + m_Platforms.push_back(std::make_unique()); } -} - -MovingPlatformComponent::~MovingPlatformComponent() { - delete static_cast(m_MoverSubComponent); + if (m_Parent->GetVar(u"platformIsMover")) { + m_Platforms.push_back(std::make_unique()); + } + if (m_Parent->GetVar(u"platformIsRotater")) { + m_Platforms.push_back(std::make_unique()); + } + m_DirtyPathInfo = true; } void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { - // Here we don't serialize the moving platform to let the client simulate the movement + // For some reason we need to write this here instead of later on. + outBitStream->Write(!m_Platforms.empty()); - if (!m_Serialize) { - outBitStream->Write(false); - outBitStream->Write(false); - - return; - } - - outBitStream->Write(true); - - auto hasPath = !m_PathingStopped && !m_PathName.empty(); - outBitStream->Write(hasPath); - - if (hasPath) { - // Is on rail - outBitStream->Write1(); - - outBitStream->Write(static_cast(m_PathName.size())); - for (const auto& c : m_PathName) { - outBitStream->Write(static_cast(c)); + outBitStream->Write(bIsInitialUpdate || m_DirtyPathInfo); + if (bIsInitialUpdate || m_DirtyPathInfo) { + outBitStream->Write(!m_PathName.empty()); + if (!m_PathName.empty()) { + outBitStream->Write(static_cast(m_PathName.size())); + for (const auto& c : m_PathName) { + outBitStream->Write(static_cast(c)); + } + outBitStream->Write(1); // Starting waypoint + outBitStream->Write1(); // is in reverse } - - // Starting point - outBitStream->Write(0); - - // Reverse - outBitStream->Write(false); + if (!bIsInitialUpdate) m_DirtyPathInfo = false; } - const auto hasPlatform = m_MoverSubComponent != nullptr; - outBitStream->Write(hasPlatform); - - if (hasPlatform) { - auto* mover = static_cast(m_MoverSubComponent); - outBitStream->Write(static_cast(m_MoverSubComponentType)); - - if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) { - // TODO - } else { - mover->Serialize(outBitStream, bIsInitialUpdate, flags); - } + for (const auto& platform : m_Platforms) { + outBitStream->Write1(); // Has platform to write + outBitStream->Write(platform->GetPlatformType()); + platform->Serialize(outBitStream, bIsInitialUpdate); } + outBitStream->Write0(); // No more platforms to write } void MovingPlatformComponent::OnRebuildInitilized() { @@ -122,232 +99,229 @@ void MovingPlatformComponent::OnRebuildInitilized() { } void MovingPlatformComponent::OnCompleteRebuild() { - if (m_NoAutoStart) - return; + if (m_NoAutoStart) return; StartPathing(); } void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) { - auto* subComponent = static_cast(m_MoverSubComponent); + // auto* subComponent = static_cast(m_MoverSubComponent); - subComponent->mState = value; + // subComponent->mState = value; - Game::entityManager->SerializeEntity(m_Parent); + // Game::entityManager->SerializeEntity(m_Parent); } void MovingPlatformComponent::GotoWaypoint(uint32_t index, bool stopAtWaypoint) { - auto* subComponent = static_cast(m_MoverSubComponent); + // auto* subComponent = static_cast(m_MoverSubComponent); - subComponent->mDesiredWaypointIndex = index; - subComponent->mNextWaypointIndex = index; - subComponent->mShouldStopAtDesiredWaypoint = stopAtWaypoint; + // subComponent->mDesiredWaypointIndex = index; + // subComponent->mNextWaypointIndex = index; + // subComponent->mShouldStopAtDesiredWaypoint = stopAtWaypoint; - StartPathing(); + // StartPathing(); } void MovingPlatformComponent::StartPathing() { - //GameMessages::SendStartPathing(m_Parent); - m_PathingStopped = false; + // //GameMessages::SendStartPathing(m_Parent); + // m_PathingStopped = false; - auto* subComponent = static_cast(m_MoverSubComponent); + // auto* subComponent = static_cast(m_MoverSubComponent); - subComponent->mShouldStopAtDesiredWaypoint = true; - subComponent->mState = eMovementPlatformState::Stationary; + // subComponent->mShouldStopAtDesiredWaypoint = true; + // subComponent->mState = eMovementPlatformState::Stationary; - NiPoint3 targetPosition; + // NiPoint3 targetPosition; - if (m_Path != nullptr) { - const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex]; - const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex]; + // if (m_Path != nullptr) { + // const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex]; + // const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex]; - subComponent->mPosition = currentWaypoint.position; - subComponent->mSpeed = currentWaypoint.movingPlatform.speed; - subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; + // subComponent->mPosition = currentWaypoint.position; + // subComponent->mSpeed = currentWaypoint.movingPlatform.speed; + // subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; - targetPosition = nextWaypoint.position; - } else { - subComponent->mPosition = m_Parent->GetPosition(); - subComponent->mSpeed = 1.0f; - subComponent->mWaitTime = 2.0f; + // targetPosition = nextWaypoint.position; + // } else { + // subComponent->mPosition = m_Parent->GetPosition(); + // subComponent->mSpeed = 1.0f; + // subComponent->mWaitTime = 2.0f; - targetPosition = m_Parent->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f); - } + // targetPosition = m_Parent->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f); + // } - m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] { - SetMovementState(eMovementPlatformState::Moving); - }); + // m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] { + // SetMovementState(eMovementPlatformState::Moving); + // }); - const auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5f; + // const auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5f; - const auto travelNext = subComponent->mWaitTime + travelTime; + // const auto travelNext = subComponent->mWaitTime + travelTime; - m_Parent->AddCallbackTimer(travelTime, [subComponent, this] { - for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex); - } - }); + // m_Parent->AddCallbackTimer(travelTime, [subComponent, this] { + // for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { + // script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex); + // } + // }); - m_Parent->AddCallbackTimer(travelNext, [this] { - ContinuePathing(); - }); + // m_Parent->AddCallbackTimer(travelNext, [this] { + // ContinuePathing(); + // }); - //GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); + // //GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); - Game::entityManager->SerializeEntity(m_Parent); + // Game::entityManager->SerializeEntity(m_Parent); } void MovingPlatformComponent::ContinuePathing() { - auto* subComponent = static_cast(m_MoverSubComponent); + // auto* subComponent = static_cast(m_MoverSubComponent); - subComponent->mState = eMovementPlatformState::Stationary; + // subComponent->mState = eMovementPlatformState::Stationary; - subComponent->mCurrentWaypointIndex = subComponent->mNextWaypointIndex; + // subComponent->mCurrentWaypointIndex = subComponent->mNextWaypointIndex; - NiPoint3 targetPosition; - uint32_t pathSize; - PathBehavior behavior; + // NiPoint3 targetPosition; + // uint32_t pathSize; + // PathBehavior behavior; - if (m_Path != nullptr) { - const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex]; - const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex]; + // if (m_Path != nullptr) { + // const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex]; + // const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex]; - subComponent->mPosition = currentWaypoint.position; - subComponent->mSpeed = currentWaypoint.movingPlatform.speed; - subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; // + 2; + // subComponent->mPosition = currentWaypoint.position; + // subComponent->mSpeed = currentWaypoint.movingPlatform.speed; + // subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; // + 2; - pathSize = m_Path->pathWaypoints.size() - 1; + // pathSize = m_Path->pathWaypoints.size() - 1; - behavior = static_cast(m_Path->pathBehavior); + // behavior = static_cast(m_Path->pathBehavior); - targetPosition = nextWaypoint.position; - } else { - subComponent->mPosition = m_Parent->GetPosition(); - subComponent->mSpeed = 1.0f; - subComponent->mWaitTime = 2.0f; + // targetPosition = nextWaypoint.position; + // } else { + // subComponent->mPosition = m_Parent->GetPosition(); + // subComponent->mSpeed = 1.0f; + // subComponent->mWaitTime = 2.0f; - targetPosition = m_Parent->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f); + // targetPosition = m_Parent->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f); - pathSize = 1; - behavior = PathBehavior::Loop; - } + // pathSize = 1; + // behavior = PathBehavior::Loop; + // } - if (m_Parent->GetLOT() == 9483) { - behavior = PathBehavior::Bounce; - } else { - return; - } + // if (m_Parent->GetLOT() == 9483) { + // behavior = PathBehavior::Bounce; + // } else { + // return; + // } - if (subComponent->mCurrentWaypointIndex >= pathSize) { - subComponent->mCurrentWaypointIndex = pathSize; - switch (behavior) { - case PathBehavior::Once: - Game::entityManager->SerializeEntity(m_Parent); - return; + // if (subComponent->mCurrentWaypointIndex >= pathSize) { + // subComponent->mCurrentWaypointIndex = pathSize; + // switch (behavior) { + // case PathBehavior::Once: + // Game::entityManager->SerializeEntity(m_Parent); + // return; - case PathBehavior::Bounce: - subComponent->mInReverse = true; - break; + // case PathBehavior::Bounce: + // subComponent->mInReverse = true; + // break; - case PathBehavior::Loop: - subComponent->mNextWaypointIndex = 0; - break; + // case PathBehavior::Loop: + // subComponent->mNextWaypointIndex = 0; + // break; - default: - break; - } - } else if (subComponent->mCurrentWaypointIndex == 0) { - subComponent->mInReverse = false; - } + // default: + // break; + // } + // } else if (subComponent->mCurrentWaypointIndex == 0) { + // subComponent->mInReverse = false; + // } - if (subComponent->mInReverse) { - subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex - 1; - } else { - subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex + 1; - } + // if (subComponent->mInReverse) { + // subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex - 1; + // } else { + // subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex + 1; + // } - /* - subComponent->mNextWaypointIndex = 0; - subComponent->mCurrentWaypointIndex = 1; - */ + // /* + // subComponent->mNextWaypointIndex = 0; + // subComponent->mCurrentWaypointIndex = 1; + // */ - //GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); + // //GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); - if (subComponent->mCurrentWaypointIndex == subComponent->mDesiredWaypointIndex) { - // TODO: Send event? - StopPathing(); + // if (subComponent->mCurrentWaypointIndex == subComponent->mDesiredWaypointIndex) { + // // TODO: Send event? + // StopPathing(); - return; - } + // return; + // } - m_Parent->CancelCallbackTimers(); + // m_Parent->CancelCallbackTimers(); - m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] { - SetMovementState(eMovementPlatformState::Moving); - }); + // m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] { + // SetMovementState(eMovementPlatformState::Moving); + // }); - auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5; + // auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5; - if (m_Parent->GetLOT() == 9483) { - travelTime += 20; - } + // if (m_Parent->GetLOT() == 9483) { + // travelTime += 20; + // } - const auto travelNext = subComponent->mWaitTime + travelTime; + // const auto travelNext = subComponent->mWaitTime + travelTime; - m_Parent->AddCallbackTimer(travelTime, [subComponent, this] { - for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex); - } - }); + // m_Parent->AddCallbackTimer(travelTime, [subComponent, this] { + // for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { + // script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex); + // } + // }); - m_Parent->AddCallbackTimer(travelNext, [this] { - ContinuePathing(); - }); + // m_Parent->AddCallbackTimer(travelNext, [this] { + // ContinuePathing(); + // }); - Game::entityManager->SerializeEntity(m_Parent); + // Game::entityManager->SerializeEntity(m_Parent); } void MovingPlatformComponent::StopPathing() { //m_Parent->CancelCallbackTimers(); - auto* subComponent = static_cast(m_MoverSubComponent); + // auto* subComponent = static_cast(m_MoverSubComponent); - m_PathingStopped = true; + // m_PathingStopped = true; - subComponent->mState = eMovementPlatformState::Stopped; - subComponent->mDesiredWaypointIndex = -1; - subComponent->mShouldStopAtDesiredWaypoint = false; + // subComponent->mState = eMovementPlatformState::Stopped; + // subComponent->mDesiredWaypointIndex = -1; + // subComponent->mShouldStopAtDesiredWaypoint = false; - Game::entityManager->SerializeEntity(m_Parent); + // Game::entityManager->SerializeEntity(m_Parent); //GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); } void MovingPlatformComponent::SetSerialized(bool value) { - m_Serialize = value; + // m_Serialize = value; } bool MovingPlatformComponent::GetNoAutoStart() const { - return m_NoAutoStart; + return false; + // return m_NoAutoStart; } void MovingPlatformComponent::SetNoAutoStart(const bool value) { - m_NoAutoStart = value; + // m_NoAutoStart = value; } void MovingPlatformComponent::WarpToWaypoint(size_t index) { - const auto& waypoint = m_Path->pathWaypoints[index]; + // const auto& waypoint = m_Path->pathWaypoints[index]; - m_Parent->SetPosition(waypoint.position); - m_Parent->SetRotation(waypoint.rotation); + // m_Parent->SetPosition(waypoint.position); + // m_Parent->SetRotation(waypoint.rotation); - Game::entityManager->SerializeEntity(m_Parent); + // Game::entityManager->SerializeEntity(m_Parent); } size_t MovingPlatformComponent::GetLastWaypointIndex() const { - return m_Path->pathWaypoints.size() - 1; -} - -MoverSubComponent* MovingPlatformComponent::GetMoverSubComponent() const { - return static_cast(m_MoverSubComponent); + return 0; + // return m_Path->pathWaypoints.size() - 1; } diff --git a/dGame/dComponents/MovingPlatformComponent.h b/dGame/dComponents/MovingPlatformComponent.h index 9e4c1ecf..06957fbc 100644 --- a/dGame/dComponents/MovingPlatformComponent.h +++ b/dGame/dComponents/MovingPlatformComponent.h @@ -6,96 +6,82 @@ #ifndef MOVINGPLATFORMCOMPONENT_H #define MOVINGPLATFORMCOMPONENT_H -#include "RakNetTypes.h" #include "NiPoint3.h" +#include #include +#include #include "dCommonVars.h" -#include "EntityManager.h" #include "Component.h" #include "eMovementPlatformState.h" #include "eReplicaComponentType.h" class Path; - /** - * Different types of available platforms - */ +/** + * Different types of available platforms + */ enum class eMoverSubComponentType : uint32_t { - mover = 4, - - /** - * Used in NJ - */ - simpleMover = 5, + None = 0, + Mover = 4, + SimpleMover = 5, + Rotator = 6 }; -/** - * Sub component for moving platforms that determine the actual current movement state - */ -class MoverSubComponent { +class PlatformSubComponent { public: - MoverSubComponent(const NiPoint3& startPos); - ~MoverSubComponent(); - - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const; + PlatformSubComponent(); + virtual ~PlatformSubComponent() = default; + virtual void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate); + virtual eMoverSubComponentType GetPlatformType() { return eMoverSubComponentType::None; }; + bool GetIsDirty() const { return m_IsDirty; } +protected: +#ifdef _MOVING_PLATFORM_TEST +public: +#endif /** * The state the platform is currently in */ - eMovementPlatformState mState = eMovementPlatformState::Stationary; - - /** - * The waypoint this platform currently wants to traverse to - */ - int32_t mDesiredWaypointIndex = 0; - - /** - * Whether the platform is currently reversing away from the desired waypoint - */ - bool mInReverse = false; - - /** - * Whether the platform should stop moving when reaching the desired waypoint - */ - bool mShouldStopAtDesiredWaypoint = false; - - /** - * The percentage of the way between the last point and the desired point - */ - float mPercentBetweenPoints = 0; - - /** - * The current position of the platofrm - */ - NiPoint3 mPosition{}; - - /** - * The waypoint the platform is (was) at - */ - uint32_t mCurrentWaypointIndex; - - /** - * The waypoint the platform is attempting to go to - */ - uint32_t mNextWaypointIndex; - - /** - * The timer that handles the time before stopping idling and continue platform movement - */ - float mIdleTimeElapsed = 0; - - /** - * The speed the platform is currently moving at - */ - float mSpeed = 0; - - /** - * The time to wait before continuing movement - */ - float mWaitTime = 0; + eMovementPlatformState m_State = eMovementPlatformState::Stopped | eMovementPlatformState::ReachedDesiredWaypoint; + int32_t m_DesiredWaypointIndex = 0; + float m_PercentBetweenPoints = 0; + NiPoint3 m_Position; + uint32_t m_CurrentWaypointIndex; + uint32_t m_NextWaypointIndex; + float m_IdleTimeElapsed = 0; + float m_Speed = 0; + float m_WaitTime = 0; + float m_MoveTimeElapsed = 0; + bool m_IsDirty = false; + bool m_InReverse = false; + bool m_ShouldStopAtDesiredWaypoint = false; }; +class MoverPlatformSubComponent : public PlatformSubComponent { +public: + MoverPlatformSubComponent() : PlatformSubComponent() {}; + ~MoverPlatformSubComponent() override = default; + eMoverSubComponentType GetPlatformType() override { return eMoverSubComponentType::Mover; } + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override { PlatformSubComponent::Serialize(outBitStream, bIsInitialUpdate); }; +}; + +class RotatorPlatformSubComponent : public PlatformSubComponent { +public: + RotatorPlatformSubComponent() : PlatformSubComponent() {}; + ~RotatorPlatformSubComponent() override = default; + eMoverSubComponentType GetPlatformType() override { return eMoverSubComponentType::Rotator; } + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override { PlatformSubComponent::Serialize(outBitStream, bIsInitialUpdate); }; +}; + +// Only moves. Has NO path. +class SimpleMoverPlatformSubComponent : public PlatformSubComponent { +public: + SimpleMoverPlatformSubComponent() : PlatformSubComponent() {}; + ~SimpleMoverPlatformSubComponent() override = default; + eMoverSubComponentType GetPlatformType() override { return eMoverSubComponentType::SimpleMover; } + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override { PlatformSubComponent::Serialize(outBitStream, bIsInitialUpdate); }; +}; /** * Represents entities that may be moving platforms, indicating how they should move through the world. @@ -109,7 +95,6 @@ public: static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM; MovingPlatformComponent(Entity* parent, const std::string& pathName); - ~MovingPlatformComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); @@ -181,19 +166,22 @@ public: */ size_t GetLastWaypointIndex() const; +#ifdef _MOVING_PLATFORM_TEST /** - * Returns the sub component that actually defines how the platform moves around (speeds, etc). - * @return the sub component that actually defines how the platform moves around + * Only used for testing. Do not call in production code. Let the constructor take care of this. + * + * @param platformSubComponent */ - MoverSubComponent* GetMoverSubComponent() const; + void _AddPlatformSubComponent(std::unique_ptr platformSubComponent) { + m_Platforms.push_back(std::move(platformSubComponent)); + } + void _SetPath(const std::u16string& path) { + m_PathName = path; + m_DirtyPathInfo = true; + } +#endif private: - - /** - * The path this platform is currently on - */ - const Path* m_Path = nullptr; - /** * The name of the path this platform is currently on */ @@ -204,15 +192,10 @@ private: */ bool m_PathingStopped = false; - /** - * The type of the subcomponent - */ - eMoverSubComponentType m_MoverSubComponentType; - /** * The mover sub component that belongs to this platform */ - void* m_MoverSubComponent; + std::vector> m_Platforms; /** * Whether the platform shouldn't auto start @@ -223,6 +206,8 @@ private: * Whether to serialize the entity on the next update */ bool m_Serialize = false; + + bool m_DirtyPathInfo = false; }; #endif // MOVINGPLATFORMCOMPONENT_H diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 8d8085a9..ef9bea48 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -362,7 +362,7 @@ void GameMessages::SendPlatformResync(Entity* entity, const SystemAddress& sysAd iIndex = 0; nextIndex = 0; bStopAtDesiredWaypoint = true; - movementState = eMovementPlatformState::Stationary; + movementState = eMovementPlatformState::Waiting | eMovementPlatformState::ReachedDesiredWaypoint | eMovementPlatformState::ReachedFinalWaypoint; } bitStream.Write(entity->GetObjectID()); diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index bd1224d3..695d8209 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -71,7 +71,7 @@ namespace GameMessages { void SendStartPathing(Entity* entity); void SendPlatformResync(Entity* entity, const SystemAddress& sysAddr, bool bStopAtDesiredWaypoint = false, int iIndex = 0, int iDesiredWaypointIndex = 1, int nextIndex = 1, - eMovementPlatformState movementState = eMovementPlatformState::Moving); + eMovementPlatformState movementState = eMovementPlatformState::Travelling); void SendRestoreToPostLoadStats(Entity* entity, const SystemAddress& sysAddr); void SendServerDoneLoadingAllObjects(Entity* entity, const SystemAddress& sysAddr); diff --git a/dScripts/02_server/Map/General/PropertyPlatform.cpp b/dScripts/02_server/Map/General/PropertyPlatform.cpp index 7016db94..b831bf48 100644 --- a/dScripts/02_server/Map/General/PropertyPlatform.cpp +++ b/dScripts/02_server/Map/General/PropertyPlatform.cpp @@ -4,24 +4,15 @@ #include "MovingPlatformComponent.h" void PropertyPlatform::OnRebuildComplete(Entity* self, Entity* target) { - // auto* movingPlatform = self->GetComponent(); - // if (movingPlatform != nullptr) { - // movingPlatform->StopPathing(); - // movingPlatform->SetNoAutoStart(true); - // } GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, - 0, 0, eMovementPlatformState::Stationary); + 0, 0, eMovementPlatformState::Waiting | eMovementPlatformState::ReachedDesiredWaypoint | eMovementPlatformState::ReachedFinalWaypoint); } void PropertyPlatform::OnUse(Entity* self, Entity* user) { auto* rebuildComponent = self->GetComponent(); if (rebuildComponent != nullptr && rebuildComponent->GetState() == eRebuildState::COMPLETED) { - // auto* movingPlatform = self->GetComponent(); - // if (movingPlatform != nullptr) { - // movingPlatform->GotoWaypoint(1); - // } GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, - 1, 1, eMovementPlatformState::Moving); + 1, 1, eMovementPlatformState::Travelling); self->AddCallbackTimer(movementDelay + effectDelay, [self, this]() { self->SetNetworkVar(u"startEffect", dieDelay); diff --git a/dScripts/ai/AG/AgQbElevator.cpp b/dScripts/ai/AG/AgQbElevator.cpp index 5a535347..b39d3198 100644 --- a/dScripts/ai/AG/AgQbElevator.cpp +++ b/dScripts/ai/AG/AgQbElevator.cpp @@ -15,7 +15,7 @@ void AgQbElevator::OnRebuildComplete(Entity* self, Entity* target) { if (delayTime < 1) delayTime = 1; GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, - 0, 0, eMovementPlatformState::Stationary); + 0, 0, eMovementPlatformState::Waiting | eMovementPlatformState::ReachedDesiredWaypoint | eMovementPlatformState::ReachedFinalWaypoint); //add a timer that will kill the QB if no players get on in the killTime self->AddTimer("startKillTimer", killTime); @@ -33,7 +33,7 @@ void AgQbElevator::OnProximityUpdate(Entity* self, Entity* entering, std::string self->CancelTimer("StartElevator"); GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, - 1, 1, eMovementPlatformState::Moving); + 1, 1, eMovementPlatformState::Travelling); } else if (!self->GetBoolean(u"StartTimer")) { self->SetBoolean(u"StartTimer", true); self->AddTimer("StartElevator", startTime); @@ -45,7 +45,7 @@ void AgQbElevator::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "StartElevator") { GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, - 1, 1, eMovementPlatformState::Moving); + 1, 1, eMovementPlatformState::Travelling); } else if (timerName == "startKillTimer") { killTimerStartup(self); } else if (timerName == "KillTimer") { diff --git a/tests/dGameTests/dComponentsTests/CMakeLists.txt b/tests/dGameTests/dComponentsTests/CMakeLists.txt index 17e69a2f..9441c8cb 100644 --- a/tests/dGameTests/dComponentsTests/CMakeLists.txt +++ b/tests/dGameTests/dComponentsTests/CMakeLists.txt @@ -1,5 +1,6 @@ set(DCOMPONENTS_TESTS "DestroyableComponentTests.cpp" + "MovingPlatformComponentTests.cpp" ) # Get the folder name and prepend it to the files above diff --git a/tests/dGameTests/dComponentsTests/MovingPlatformComponentTests.cpp b/tests/dGameTests/dComponentsTests/MovingPlatformComponentTests.cpp new file mode 100644 index 00000000..d055e88a --- /dev/null +++ b/tests/dGameTests/dComponentsTests/MovingPlatformComponentTests.cpp @@ -0,0 +1,158 @@ +#include "GameDependencies.h" +#include + +#include "BitStream.h" +#include "Entity.h" + +#define _MOVING_PLATFORM_TEST +#include "MovingPlatformComponent.h" +#undef _MOVING_PLATFORM_TEST +#include "eReplicaComponentType.h" + +class MovingPlatformComponentTests : public GameDependenciesTest { +protected: + std::unique_ptr baseEntity; + CBITSTREAM; + uint32_t flags = 0; + void SetUp() override { + SetUpDependencies(); + baseEntity = std::make_unique(15, GameDependenciesTest::info); + auto* movingPlatformComponent = new MovingPlatformComponent(baseEntity.get(), ""); + baseEntity->AddComponent(eReplicaComponentType::MOVING_PLATFORM, movingPlatformComponent); + auto moverPlatformSubComponent = std::make_unique(); + moverPlatformSubComponent->m_State = eMovementPlatformState::Stopped | eMovementPlatformState::ReachedDesiredWaypoint; + moverPlatformSubComponent->m_DesiredWaypointIndex = 1; + moverPlatformSubComponent->m_PercentBetweenPoints = 2; + moverPlatformSubComponent->m_Position = NiPoint3(3, 4, 5); + moverPlatformSubComponent->m_CurrentWaypointIndex = 6; + moverPlatformSubComponent->m_NextWaypointIndex = 7; + moverPlatformSubComponent->m_IdleTimeElapsed = 8; + moverPlatformSubComponent->m_MoveTimeElapsed = 11; + moverPlatformSubComponent->m_IsDirty = true; + moverPlatformSubComponent->m_InReverse = true; + moverPlatformSubComponent->m_ShouldStopAtDesiredWaypoint = true; + + auto rotatorPlatformSubComponent = std::make_unique(); + rotatorPlatformSubComponent->m_State = eMovementPlatformState::Travelling; + rotatorPlatformSubComponent->m_DesiredWaypointIndex = 12; + rotatorPlatformSubComponent->m_PercentBetweenPoints = 13; + rotatorPlatformSubComponent->m_Position = NiPoint3(14, 15, 16); + rotatorPlatformSubComponent->m_CurrentWaypointIndex = 17; + rotatorPlatformSubComponent->m_NextWaypointIndex = 18; + rotatorPlatformSubComponent->m_IdleTimeElapsed = 19; + rotatorPlatformSubComponent->m_MoveTimeElapsed = 22; + rotatorPlatformSubComponent->m_IsDirty = true; + rotatorPlatformSubComponent->m_InReverse = true; + rotatorPlatformSubComponent->m_ShouldStopAtDesiredWaypoint = true; + + auto simpleMoverPlatformSubComponent = std::make_unique(); + simpleMoverPlatformSubComponent->m_State = eMovementPlatformState::Waiting | eMovementPlatformState::ReachedDesiredWaypoint | eMovementPlatformState::ReachedFinalWaypoint; + simpleMoverPlatformSubComponent->m_DesiredWaypointIndex = 23; + simpleMoverPlatformSubComponent->m_PercentBetweenPoints = 24; + simpleMoverPlatformSubComponent->m_Position = NiPoint3(25, 26, 27); + simpleMoverPlatformSubComponent->m_CurrentWaypointIndex = 28; + simpleMoverPlatformSubComponent->m_NextWaypointIndex = 29; + simpleMoverPlatformSubComponent->m_IdleTimeElapsed = 30; + simpleMoverPlatformSubComponent->m_MoveTimeElapsed = 33; + simpleMoverPlatformSubComponent->m_IsDirty = true; + simpleMoverPlatformSubComponent->m_InReverse = true; + simpleMoverPlatformSubComponent->m_ShouldStopAtDesiredWaypoint = true; + + movingPlatformComponent->_AddPlatformSubComponent(std::move(moverPlatformSubComponent)); + movingPlatformComponent->_AddPlatformSubComponent(std::move(rotatorPlatformSubComponent)); + movingPlatformComponent->_AddPlatformSubComponent(std::move(simpleMoverPlatformSubComponent)); + movingPlatformComponent->_SetPath(u"ExamplePath"); + } + + void TearDown() override { + TearDownDependencies(); + } +}; + +TEST_F(MovingPlatformComponentTests, MovingPlatformConstructionTest) { + auto* movingPlatformComponent = baseEntity->GetComponent(); + ASSERT_NE(movingPlatformComponent, nullptr); + uint32_t flags = 0; + movingPlatformComponent->Serialize(&bitStream, true, flags); + // read in the full BitStream and check the values match what they were set to above + bool hasPlatformSubComponents = false; + bitStream.Read(hasPlatformSubComponents); + ASSERT_TRUE(hasPlatformSubComponents); + + bool dirtyPathInfo; + bitStream.Read(dirtyPathInfo); + ASSERT_TRUE(dirtyPathInfo); + + bool hasPath; + bitStream.Read(hasPath); + ASSERT_TRUE(hasPath); + + std::u16string pathName; + uint16_t pathNameLength; + bitStream.Read(pathNameLength); + pathName.resize(pathNameLength); + bitStream.ReadBits(reinterpret_cast(pathName.data()), BYTES_TO_BITS(pathNameLength) * 2); + ASSERT_EQ(pathName, u"ExamplePath"); + + uint32_t pathStartIndex; + bitStream.Read(pathStartIndex); + ASSERT_EQ(pathStartIndex, 1); + + bool isInReverse; + bitStream.Read(isInReverse); + ASSERT_TRUE(isInReverse); + + bool hasPlatformData; + bitStream.Read(hasPlatformData); + ASSERT_TRUE(hasPlatformData); + + eMoverSubComponentType platformType; + bitStream.Read(platformType); + ASSERT_EQ(platformType, eMoverSubComponentType::Mover); + + bool isDirty; + bitStream.Read(isDirty); + ASSERT_TRUE(isDirty); + + eMovementPlatformState state; + bitStream.Read(state); + ASSERT_EQ(state, eMovementPlatformState::Stopped | eMovementPlatformState::ReachedDesiredWaypoint); + + int32_t desiredWaypointIndex; + bitStream.Read(desiredWaypointIndex); + ASSERT_EQ(desiredWaypointIndex, 1); + + bool shouldStopAtDesiredWaypoint; + bitStream.Read(shouldStopAtDesiredWaypoint); + ASSERT_TRUE(shouldStopAtDesiredWaypoint); + + bool isInReverse2; + bitStream.Read(isInReverse2); + ASSERT_TRUE(isInReverse2); + + float percentBetweenPoints; + bitStream.Read(percentBetweenPoints); + ASSERT_EQ(percentBetweenPoints, 2); + + NiPoint3 position; + bitStream.Read(position.x); + bitStream.Read(position.y); + bitStream.Read(position.z); + ASSERT_EQ(position, NiPoint3(3, 4, 5)); + + uint32_t currentWaypointIndex; + bitStream.Read(currentWaypointIndex); + ASSERT_EQ(currentWaypointIndex, 6); + + uint32_t nextWaypointIndex; + bitStream.Read(nextWaypointIndex); + ASSERT_EQ(nextWaypointIndex, 7); + + float idleTimeElapsed; + bitStream.Read(idleTimeElapsed); + ASSERT_EQ(idleTimeElapsed, 8); + + float moveTimeElapsed; + bitStream.Read(moveTimeElapsed); + ASSERT_EQ(moveTimeElapsed, 11); +}