throw away the old impl

This commit is contained in:
David Markowitz 2023-07-31 02:13:19 -07:00
parent 0d48cfe8c0
commit 3cf460cc52
9 changed files with 442 additions and 327 deletions

View File

@ -4,13 +4,19 @@
#include <cstdint> #include <cstdint>
/** /**
* The different types of platform movement state, supposedly a bitmap * The different types of platform movement state
*/ */
enum class eMovementPlatformState : uint32_t enum class eMovementPlatformState : uint32_t
{ {
Moving = 0b00010, Waiting = 1 << 0U,
Stationary = 0b11001, Travelling = 1 << 1U,
Stopped = 0b01100 Stopped = 1 << 2U,
ReachedDesiredWaypoint = 1 << 3U,
ReachedFinalWaypoint = 1 << 4U,
};
inline constexpr eMovementPlatformState operator|(eMovementPlatformState a, eMovementPlatformState b) {
return static_cast<eMovementPlatformState>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
}; };
#endif //!__EMOVEMENTPLATFORMSTATE__H__ #endif //!__EMOVEMENTPLATFORMSTATE__H__

View File

@ -14,107 +14,84 @@
#include "SimplePhysicsComponent.h" #include "SimplePhysicsComponent.h"
#include "Zone.h" #include "Zone.h"
MoverSubComponent::MoverSubComponent(const NiPoint3& startPos) { PlatformSubComponent::PlatformSubComponent() {
mPosition = {}; m_Position = NiPoint3::ZERO;
mState = eMovementPlatformState::Stopped; m_State = eMovementPlatformState::Stopped | eMovementPlatformState::ReachedDesiredWaypoint;
mDesiredWaypointIndex = 0; // -1; m_DesiredWaypointIndex = 0;
mInReverse = false; m_InReverse = false;
mShouldStopAtDesiredWaypoint = false; m_ShouldStopAtDesiredWaypoint = false;
mPercentBetweenPoints = 0.0f; m_PercentBetweenPoints = 0.0f;
mCurrentWaypointIndex = 0; m_CurrentWaypointIndex = 0;
mNextWaypointIndex = 0; //mCurrentWaypointIndex + 1; m_NextWaypointIndex = 0;
mIdleTimeElapsed = 0.0f; m_IdleTimeElapsed = 0.0f;
} }
MoverSubComponent::~MoverSubComponent() = default; void PlatformSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
outBitStream->Write(m_IsDirty);
void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const { if (!m_IsDirty) return;
outBitStream->Write<bool>(true); outBitStream->Write(m_State);
outBitStream->Write(m_DesiredWaypointIndex);
outBitStream->Write<uint32_t>(static_cast<uint32_t>(mState)); outBitStream->Write(m_ShouldStopAtDesiredWaypoint);
outBitStream->Write<int32_t>(mDesiredWaypointIndex); outBitStream->Write(m_InReverse);
outBitStream->Write(mShouldStopAtDesiredWaypoint); outBitStream->Write(m_PercentBetweenPoints);
outBitStream->Write(mInReverse); outBitStream->Write(m_Position.x);
outBitStream->Write(m_Position.y);
outBitStream->Write<float_t>(mPercentBetweenPoints); outBitStream->Write(m_Position.z);
outBitStream->Write(m_CurrentWaypointIndex);
outBitStream->Write<float_t>(mPosition.x); outBitStream->Write(m_NextWaypointIndex);
outBitStream->Write<float_t>(mPosition.y); outBitStream->Write(m_IdleTimeElapsed);
outBitStream->Write<float_t>(mPosition.z); outBitStream->Write(m_MoveTimeElapsed);
if (!bIsInitialUpdate) m_IsDirty = false;
outBitStream->Write<uint32_t>(mCurrentWaypointIndex);
outBitStream->Write<uint32_t>(mNextWaypointIndex);
outBitStream->Write<float_t>(mIdleTimeElapsed);
outBitStream->Write<float_t>(0.0f); // Move time elapsed
} }
//------------- MovingPlatformComponent below -------------- //------------- MovingPlatformComponent below --------------
MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::string& pathName) : Component(parent) { MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::string& pathName) : Component(parent) {
m_MoverSubComponentType = eMoverSubComponentType::mover; if (Game::zoneManager == nullptr) return;
m_MoverSubComponent = new MoverSubComponent(m_Parent->GetDefaultPosition()); auto path = Game::zoneManager->GetZone()->GetPath(pathName);
m_PathName = GeneralUtils::ASCIIToUTF16(pathName); if (!path) return;
m_Path = Game::zoneManager->GetZone()->GetPath(pathName); Game::logger->Log("MovingPlatformComponent", "Path found: %s", pathName.c_str());
m_NoAutoStart = false;
if (m_Path == nullptr) { if (m_Parent->GetVar<bool>(u"platformIsSimpleMover")) {
Game::logger->Log("MovingPlatformComponent", "Path not found: %s", pathName.c_str()); m_Platforms.push_back(std::make_unique<SimpleMoverPlatformSubComponent>());
} }
} if (m_Parent->GetVar<bool>(u"platformIsMover")) {
m_Platforms.push_back(std::make_unique<MoverPlatformSubComponent>());
MovingPlatformComponent::~MovingPlatformComponent() { }
delete static_cast<MoverSubComponent*>(m_MoverSubComponent); if (m_Parent->GetVar<bool>(u"platformIsRotater")) {
m_Platforms.push_back(std::make_unique<RotatorPlatformSubComponent>());
}
m_DirtyPathInfo = true;
} }
void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { 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<bool>(false);
outBitStream->Write<bool>(false);
return;
}
outBitStream->Write<bool>(true);
auto hasPath = !m_PathingStopped && !m_PathName.empty();
outBitStream->Write(hasPath);
if (hasPath) {
// Is on rail
outBitStream->Write1();
outBitStream->Write(bIsInitialUpdate || m_DirtyPathInfo);
if (bIsInitialUpdate || m_DirtyPathInfo) {
outBitStream->Write(!m_PathName.empty());
if (!m_PathName.empty()) {
outBitStream->Write(static_cast<uint16_t>(m_PathName.size())); outBitStream->Write(static_cast<uint16_t>(m_PathName.size()));
for (const auto& c : m_PathName) { for (const auto& c : m_PathName) {
outBitStream->Write(static_cast<uint16_t>(c)); outBitStream->Write(static_cast<uint16_t>(c));
} }
outBitStream->Write<uint32_t>(1); // Starting waypoint
// Starting point outBitStream->Write1(); // is in reverse
outBitStream->Write<uint32_t>(0); }
if (!bIsInitialUpdate) m_DirtyPathInfo = false;
// Reverse
outBitStream->Write<bool>(false);
} }
const auto hasPlatform = m_MoverSubComponent != nullptr; for (const auto& platform : m_Platforms) {
outBitStream->Write<bool>(hasPlatform); outBitStream->Write1(); // Has platform to write
outBitStream->Write(platform->GetPlatformType());
if (hasPlatform) { platform->Serialize(outBitStream, bIsInitialUpdate);
auto* mover = static_cast<MoverSubComponent*>(m_MoverSubComponent);
outBitStream->Write<uint32_t>(static_cast<uint32_t>(m_MoverSubComponentType));
if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) {
// TODO
} else {
mover->Serialize(outBitStream, bIsInitialUpdate, flags);
}
} }
outBitStream->Write0(); // No more platforms to write
} }
void MovingPlatformComponent::OnRebuildInitilized() { void MovingPlatformComponent::OnRebuildInitilized() {
@ -122,232 +99,229 @@ void MovingPlatformComponent::OnRebuildInitilized() {
} }
void MovingPlatformComponent::OnCompleteRebuild() { void MovingPlatformComponent::OnCompleteRebuild() {
if (m_NoAutoStart) if (m_NoAutoStart) return;
return;
StartPathing(); StartPathing();
} }
void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) { void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) {
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent); // auto* subComponent = static_cast<MoverSubComponent*>(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) { void MovingPlatformComponent::GotoWaypoint(uint32_t index, bool stopAtWaypoint) {
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent); // auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
subComponent->mDesiredWaypointIndex = index; // subComponent->mDesiredWaypointIndex = index;
subComponent->mNextWaypointIndex = index; // subComponent->mNextWaypointIndex = index;
subComponent->mShouldStopAtDesiredWaypoint = stopAtWaypoint; // subComponent->mShouldStopAtDesiredWaypoint = stopAtWaypoint;
StartPathing(); // StartPathing();
} }
void MovingPlatformComponent::StartPathing() { void MovingPlatformComponent::StartPathing() {
//GameMessages::SendStartPathing(m_Parent); // //GameMessages::SendStartPathing(m_Parent);
m_PathingStopped = false; // m_PathingStopped = false;
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent); // auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
subComponent->mShouldStopAtDesiredWaypoint = true; // subComponent->mShouldStopAtDesiredWaypoint = true;
subComponent->mState = eMovementPlatformState::Stationary; // subComponent->mState = eMovementPlatformState::Stationary;
NiPoint3 targetPosition; // NiPoint3 targetPosition;
if (m_Path != nullptr) { // if (m_Path != nullptr) {
const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex]; // const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex];
const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex]; // const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex];
subComponent->mPosition = currentWaypoint.position; // subComponent->mPosition = currentWaypoint.position;
subComponent->mSpeed = currentWaypoint.movingPlatform.speed; // subComponent->mSpeed = currentWaypoint.movingPlatform.speed;
subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; // subComponent->mWaitTime = currentWaypoint.movingPlatform.wait;
targetPosition = nextWaypoint.position; // targetPosition = nextWaypoint.position;
} else { // } else {
subComponent->mPosition = m_Parent->GetPosition(); // subComponent->mPosition = m_Parent->GetPosition();
subComponent->mSpeed = 1.0f; // subComponent->mSpeed = 1.0f;
subComponent->mWaitTime = 2.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] { // m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] {
SetMovementState(eMovementPlatformState::Moving); // 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] { // m_Parent->AddCallbackTimer(travelTime, [subComponent, this] {
for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { // for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) {
script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex); // script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex);
} // }
}); // });
m_Parent->AddCallbackTimer(travelNext, [this] { // m_Parent->AddCallbackTimer(travelNext, [this] {
ContinuePathing(); // 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() { void MovingPlatformComponent::ContinuePathing() {
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent); // auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
subComponent->mState = eMovementPlatformState::Stationary; // subComponent->mState = eMovementPlatformState::Stationary;
subComponent->mCurrentWaypointIndex = subComponent->mNextWaypointIndex; // subComponent->mCurrentWaypointIndex = subComponent->mNextWaypointIndex;
NiPoint3 targetPosition; // NiPoint3 targetPosition;
uint32_t pathSize; // uint32_t pathSize;
PathBehavior behavior; // PathBehavior behavior;
if (m_Path != nullptr) { // if (m_Path != nullptr) {
const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex]; // const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex];
const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex]; // const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex];
subComponent->mPosition = currentWaypoint.position; // subComponent->mPosition = currentWaypoint.position;
subComponent->mSpeed = currentWaypoint.movingPlatform.speed; // subComponent->mSpeed = currentWaypoint.movingPlatform.speed;
subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; // + 2; // subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; // + 2;
pathSize = m_Path->pathWaypoints.size() - 1; // pathSize = m_Path->pathWaypoints.size() - 1;
behavior = static_cast<PathBehavior>(m_Path->pathBehavior); // behavior = static_cast<PathBehavior>(m_Path->pathBehavior);
targetPosition = nextWaypoint.position; // targetPosition = nextWaypoint.position;
} else { // } else {
subComponent->mPosition = m_Parent->GetPosition(); // subComponent->mPosition = m_Parent->GetPosition();
subComponent->mSpeed = 1.0f; // subComponent->mSpeed = 1.0f;
subComponent->mWaitTime = 2.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; // pathSize = 1;
behavior = PathBehavior::Loop; // behavior = PathBehavior::Loop;
} // }
if (m_Parent->GetLOT() == 9483) { // if (m_Parent->GetLOT() == 9483) {
behavior = PathBehavior::Bounce; // behavior = PathBehavior::Bounce;
} else { // } else {
return; // return;
} // }
if (subComponent->mCurrentWaypointIndex >= pathSize) { // if (subComponent->mCurrentWaypointIndex >= pathSize) {
subComponent->mCurrentWaypointIndex = pathSize; // subComponent->mCurrentWaypointIndex = pathSize;
switch (behavior) { // switch (behavior) {
case PathBehavior::Once: // case PathBehavior::Once:
Game::entityManager->SerializeEntity(m_Parent); // Game::entityManager->SerializeEntity(m_Parent);
return; // return;
case PathBehavior::Bounce: // case PathBehavior::Bounce:
subComponent->mInReverse = true; // subComponent->mInReverse = true;
break; // break;
case PathBehavior::Loop: // case PathBehavior::Loop:
subComponent->mNextWaypointIndex = 0; // subComponent->mNextWaypointIndex = 0;
break; // break;
default: // default:
break; // break;
} // }
} else if (subComponent->mCurrentWaypointIndex == 0) { // } else if (subComponent->mCurrentWaypointIndex == 0) {
subComponent->mInReverse = false; // subComponent->mInReverse = false;
} // }
if (subComponent->mInReverse) { // if (subComponent->mInReverse) {
subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex - 1; // subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex - 1;
} else { // } else {
subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex + 1; // subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex + 1;
} // }
/* // /*
subComponent->mNextWaypointIndex = 0; // subComponent->mNextWaypointIndex = 0;
subComponent->mCurrentWaypointIndex = 1; // subComponent->mCurrentWaypointIndex = 1;
*/ // */
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); // //GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
if (subComponent->mCurrentWaypointIndex == subComponent->mDesiredWaypointIndex) { // if (subComponent->mCurrentWaypointIndex == subComponent->mDesiredWaypointIndex) {
// TODO: Send event? // // TODO: Send event?
StopPathing(); // StopPathing();
return; // return;
} // }
m_Parent->CancelCallbackTimers(); // m_Parent->CancelCallbackTimers();
m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] { // m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] {
SetMovementState(eMovementPlatformState::Moving); // 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) { // if (m_Parent->GetLOT() == 9483) {
travelTime += 20; // travelTime += 20;
} // }
const auto travelNext = subComponent->mWaitTime + travelTime; // const auto travelNext = subComponent->mWaitTime + travelTime;
m_Parent->AddCallbackTimer(travelTime, [subComponent, this] { // m_Parent->AddCallbackTimer(travelTime, [subComponent, this] {
for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { // for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) {
script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex); // script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex);
} // }
}); // });
m_Parent->AddCallbackTimer(travelNext, [this] { // m_Parent->AddCallbackTimer(travelNext, [this] {
ContinuePathing(); // ContinuePathing();
}); // });
Game::entityManager->SerializeEntity(m_Parent); // Game::entityManager->SerializeEntity(m_Parent);
} }
void MovingPlatformComponent::StopPathing() { void MovingPlatformComponent::StopPathing() {
//m_Parent->CancelCallbackTimers(); //m_Parent->CancelCallbackTimers();
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent); // auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
m_PathingStopped = true; // m_PathingStopped = true;
subComponent->mState = eMovementPlatformState::Stopped; // subComponent->mState = eMovementPlatformState::Stopped;
subComponent->mDesiredWaypointIndex = -1; // subComponent->mDesiredWaypointIndex = -1;
subComponent->mShouldStopAtDesiredWaypoint = false; // subComponent->mShouldStopAtDesiredWaypoint = false;
Game::entityManager->SerializeEntity(m_Parent); // Game::entityManager->SerializeEntity(m_Parent);
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); //GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
} }
void MovingPlatformComponent::SetSerialized(bool value) { void MovingPlatformComponent::SetSerialized(bool value) {
m_Serialize = value; // m_Serialize = value;
} }
bool MovingPlatformComponent::GetNoAutoStart() const { bool MovingPlatformComponent::GetNoAutoStart() const {
return m_NoAutoStart; return false;
// return m_NoAutoStart;
} }
void MovingPlatformComponent::SetNoAutoStart(const bool value) { void MovingPlatformComponent::SetNoAutoStart(const bool value) {
m_NoAutoStart = value; // m_NoAutoStart = value;
} }
void MovingPlatformComponent::WarpToWaypoint(size_t index) { 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->SetPosition(waypoint.position);
m_Parent->SetRotation(waypoint.rotation); // m_Parent->SetRotation(waypoint.rotation);
Game::entityManager->SerializeEntity(m_Parent); // Game::entityManager->SerializeEntity(m_Parent);
} }
size_t MovingPlatformComponent::GetLastWaypointIndex() const { size_t MovingPlatformComponent::GetLastWaypointIndex() const {
return m_Path->pathWaypoints.size() - 1; return 0;
} // return m_Path->pathWaypoints.size() - 1;
MoverSubComponent* MovingPlatformComponent::GetMoverSubComponent() const {
return static_cast<MoverSubComponent*>(m_MoverSubComponent);
} }

View File

@ -6,96 +6,82 @@
#ifndef MOVINGPLATFORMCOMPONENT_H #ifndef MOVINGPLATFORMCOMPONENT_H
#define MOVINGPLATFORMCOMPONENT_H #define MOVINGPLATFORMCOMPONENT_H
#include "RakNetTypes.h"
#include "NiPoint3.h" #include "NiPoint3.h"
#include <memory>
#include <string> #include <string>
#include <vector>
#include "dCommonVars.h" #include "dCommonVars.h"
#include "EntityManager.h"
#include "Component.h" #include "Component.h"
#include "eMovementPlatformState.h" #include "eMovementPlatformState.h"
#include "eReplicaComponentType.h" #include "eReplicaComponentType.h"
class Path; class Path;
/** /**
* Different types of available platforms * Different types of available platforms
*/ */
enum class eMoverSubComponentType : uint32_t { enum class eMoverSubComponentType : uint32_t {
mover = 4, None = 0,
Mover = 4,
/** SimpleMover = 5,
* Used in NJ Rotator = 6
*/
simpleMover = 5,
}; };
/** class PlatformSubComponent {
* Sub component for moving platforms that determine the actual current movement state
*/
class MoverSubComponent {
public: public:
MoverSubComponent(const NiPoint3& startPos); PlatformSubComponent();
~MoverSubComponent(); virtual ~PlatformSubComponent() = default;
virtual void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate);
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const; 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 * The state the platform is currently in
*/ */
eMovementPlatformState mState = eMovementPlatformState::Stationary; eMovementPlatformState m_State = eMovementPlatformState::Stopped | eMovementPlatformState::ReachedDesiredWaypoint;
int32_t m_DesiredWaypointIndex = 0;
/** float m_PercentBetweenPoints = 0;
* The waypoint this platform currently wants to traverse to NiPoint3 m_Position;
*/ uint32_t m_CurrentWaypointIndex;
int32_t mDesiredWaypointIndex = 0; uint32_t m_NextWaypointIndex;
float m_IdleTimeElapsed = 0;
/** float m_Speed = 0;
* Whether the platform is currently reversing away from the desired waypoint float m_WaitTime = 0;
*/ float m_MoveTimeElapsed = 0;
bool mInReverse = false; bool m_IsDirty = false;
bool m_InReverse = false;
/** bool m_ShouldStopAtDesiredWaypoint = 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;
}; };
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. * 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; static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM;
MovingPlatformComponent(Entity* parent, const std::string& pathName); MovingPlatformComponent(Entity* parent, const std::string& pathName);
~MovingPlatformComponent() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
@ -181,19 +166,22 @@ public:
*/ */
size_t GetLastWaypointIndex() const; size_t GetLastWaypointIndex() const;
#ifdef _MOVING_PLATFORM_TEST
/** /**
* Returns the sub component that actually defines how the platform moves around (speeds, etc). * Only used for testing. Do not call in production code. Let the constructor take care of this.
* @return the sub component that actually defines how the platform moves around *
* @param platformSubComponent
*/ */
MoverSubComponent* GetMoverSubComponent() const; void _AddPlatformSubComponent(std::unique_ptr<PlatformSubComponent> platformSubComponent) {
m_Platforms.push_back(std::move(platformSubComponent));
}
void _SetPath(const std::u16string& path) {
m_PathName = path;
m_DirtyPathInfo = true;
}
#endif
private: private:
/**
* The path this platform is currently on
*/
const Path* m_Path = nullptr;
/** /**
* The name of the path this platform is currently on * The name of the path this platform is currently on
*/ */
@ -204,15 +192,10 @@ private:
*/ */
bool m_PathingStopped = false; bool m_PathingStopped = false;
/**
* The type of the subcomponent
*/
eMoverSubComponentType m_MoverSubComponentType;
/** /**
* The mover sub component that belongs to this platform * The mover sub component that belongs to this platform
*/ */
void* m_MoverSubComponent; std::vector<std::unique_ptr<PlatformSubComponent>> m_Platforms;
/** /**
* Whether the platform shouldn't auto start * Whether the platform shouldn't auto start
@ -223,6 +206,8 @@ private:
* Whether to serialize the entity on the next update * Whether to serialize the entity on the next update
*/ */
bool m_Serialize = false; bool m_Serialize = false;
bool m_DirtyPathInfo = false;
}; };
#endif // MOVINGPLATFORMCOMPONENT_H #endif // MOVINGPLATFORMCOMPONENT_H

View File

@ -362,7 +362,7 @@ void GameMessages::SendPlatformResync(Entity* entity, const SystemAddress& sysAd
iIndex = 0; iIndex = 0;
nextIndex = 0; nextIndex = 0;
bStopAtDesiredWaypoint = true; bStopAtDesiredWaypoint = true;
movementState = eMovementPlatformState::Stationary; movementState = eMovementPlatformState::Waiting | eMovementPlatformState::ReachedDesiredWaypoint | eMovementPlatformState::ReachedFinalWaypoint;
} }
bitStream.Write(entity->GetObjectID()); bitStream.Write(entity->GetObjectID());

View File

@ -71,7 +71,7 @@ namespace GameMessages {
void SendStartPathing(Entity* entity); void SendStartPathing(Entity* entity);
void SendPlatformResync(Entity* entity, const SystemAddress& sysAddr, bool bStopAtDesiredWaypoint = false, void SendPlatformResync(Entity* entity, const SystemAddress& sysAddr, bool bStopAtDesiredWaypoint = false,
int iIndex = 0, int iDesiredWaypointIndex = 1, int nextIndex = 1, 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 SendRestoreToPostLoadStats(Entity* entity, const SystemAddress& sysAddr);
void SendServerDoneLoadingAllObjects(Entity* entity, const SystemAddress& sysAddr); void SendServerDoneLoadingAllObjects(Entity* entity, const SystemAddress& sysAddr);

View File

@ -4,24 +4,15 @@
#include "MovingPlatformComponent.h" #include "MovingPlatformComponent.h"
void PropertyPlatform::OnRebuildComplete(Entity* self, Entity* target) { void PropertyPlatform::OnRebuildComplete(Entity* self, Entity* target) {
// auto* movingPlatform = self->GetComponent<MovingPlatformComponent>();
// if (movingPlatform != nullptr) {
// movingPlatform->StopPathing();
// movingPlatform->SetNoAutoStart(true);
// }
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, 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) { void PropertyPlatform::OnUse(Entity* self, Entity* user) {
auto* rebuildComponent = self->GetComponent<RebuildComponent>(); auto* rebuildComponent = self->GetComponent<RebuildComponent>();
if (rebuildComponent != nullptr && rebuildComponent->GetState() == eRebuildState::COMPLETED) { if (rebuildComponent != nullptr && rebuildComponent->GetState() == eRebuildState::COMPLETED) {
// auto* movingPlatform = self->GetComponent<MovingPlatformComponent>();
// if (movingPlatform != nullptr) {
// movingPlatform->GotoWaypoint(1);
// }
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0,
1, 1, eMovementPlatformState::Moving); 1, 1, eMovementPlatformState::Travelling);
self->AddCallbackTimer(movementDelay + effectDelay, [self, this]() { self->AddCallbackTimer(movementDelay + effectDelay, [self, this]() {
self->SetNetworkVar<float_t>(u"startEffect", dieDelay); self->SetNetworkVar<float_t>(u"startEffect", dieDelay);

View File

@ -15,7 +15,7 @@ void AgQbElevator::OnRebuildComplete(Entity* self, Entity* target) {
if (delayTime < 1) delayTime = 1; if (delayTime < 1) delayTime = 1;
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, 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 //add a timer that will kill the QB if no players get on in the killTime
self->AddTimer("startKillTimer", killTime); self->AddTimer("startKillTimer", killTime);
@ -33,7 +33,7 @@ void AgQbElevator::OnProximityUpdate(Entity* self, Entity* entering, std::string
self->CancelTimer("StartElevator"); self->CancelTimer("StartElevator");
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0,
1, 1, eMovementPlatformState::Moving); 1, 1, eMovementPlatformState::Travelling);
} else if (!self->GetBoolean(u"StartTimer")) { } else if (!self->GetBoolean(u"StartTimer")) {
self->SetBoolean(u"StartTimer", true); self->SetBoolean(u"StartTimer", true);
self->AddTimer("StartElevator", startTime); self->AddTimer("StartElevator", startTime);
@ -45,7 +45,7 @@ void AgQbElevator::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "StartElevator") { if (timerName == "StartElevator") {
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0,
1, 1, eMovementPlatformState::Moving); 1, 1, eMovementPlatformState::Travelling);
} else if (timerName == "startKillTimer") { } else if (timerName == "startKillTimer") {
killTimerStartup(self); killTimerStartup(self);
} else if (timerName == "KillTimer") { } else if (timerName == "KillTimer") {

View File

@ -1,5 +1,6 @@
set(DCOMPONENTS_TESTS set(DCOMPONENTS_TESTS
"DestroyableComponentTests.cpp" "DestroyableComponentTests.cpp"
"MovingPlatformComponentTests.cpp"
) )
# Get the folder name and prepend it to the files above # Get the folder name and prepend it to the files above

View File

@ -0,0 +1,158 @@
#include "GameDependencies.h"
#include <gtest/gtest.h>
#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<Entity> baseEntity;
CBITSTREAM;
uint32_t flags = 0;
void SetUp() override {
SetUpDependencies();
baseEntity = std::make_unique<Entity>(15, GameDependenciesTest::info);
auto* movingPlatformComponent = new MovingPlatformComponent(baseEntity.get(), "");
baseEntity->AddComponent(eReplicaComponentType::MOVING_PLATFORM, movingPlatformComponent);
auto moverPlatformSubComponent = std::make_unique<MoverPlatformSubComponent>();
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>();
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>();
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<MovingPlatformComponent>();
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<unsigned char*>(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);
}