Skip to content

Commit

Permalink
Server: Implement #6 and #7
Browse files Browse the repository at this point in the history
  • Loading branch information
SirLynix committed Feb 21, 2018
1 parent 413d792 commit 0f92d21
Show file tree
Hide file tree
Showing 22 changed files with 246 additions and 80 deletions.
28 changes: 23 additions & 5 deletions src/Server/Components/NavigationComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,50 @@

namespace ewn
{
std::pair<Nz::Vector3f /*thrust*/, Nz::Vector3f /*rotation*/> NavigationComponent::ComputeMovement(float elapsedTime, const Nz::Vector3f& position, const Nz::Quaternionf& rotation, const Nz::Vector3f& linearVel, const Nz::Vector3f& angularVel)
{
NavigationComponent::NavigationResults NavigationComponent::ComputeMovement(float elapsedTime, const Nz::Vector3f& position, const Nz::Quaternionf& rotation, const Nz::Vector3f& linearVel, const Nz::Vector3f& angularVel)
{
Nz::Vector3f targetPos;
std::visit([&targetPos](auto&& arg)
bool hasTarget = std::visit([&targetPos](auto&& arg) -> bool
{
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, Nz::Vector3f>)
{
targetPos = arg;
return true;
}
else if constexpr (std::is_same_v<T, Ndk::EntityHandle>)
{
if (!arg)
return false;

targetPos = arg->GetComponent<Ndk::NodeComponent>().GetPosition();
return true;
}
else if constexpr (std::is_same_v<T, std::monostate>)
assert(false); //< ComputeMovement is not supposed to be called when there's no target
return false;
else
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");

}, m_target);

if (!hasTarget)
return { Nz::Vector3f::Zero(), Nz::Vector3f::Zero() };

Nz::Vector3f desiredHeading = targetPos - position;
bool isCloseEnough = (desiredHeading.GetSquaredLength() <= m_triggerDistance * m_triggerDistance);

desiredHeading.Normalize();

Nz::Vector3f currentHeading = rotation * Nz::Vector3f::Forward();
Nz::Vector3f headingError = currentHeading.CrossProduct(desiredHeading);

Nz::Vector3f torque = m_headingController.Update(headingError, elapsedTime);

return { Nz::Vector3f::Zero(), torque };
Nz::Vector3f force = Nz::Vector3f::Zero();
if (currentHeading.DotProduct(desiredHeading) > 0.95)
force = Nz::Vector3f::Forward();

return { force, torque, isCloseEnough };
}

Ndk::ComponentIndex NavigationComponent::componentIndex;
Expand Down
19 changes: 17 additions & 2 deletions src/Server/Components/NavigationComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <Nazara/Math/Vector3.hpp>
#include <NDK/Component.hpp>
#include <Shared/Utils/PidController.hpp>
#include <functional>
#include <variant>
#include <vector>

Expand All @@ -19,32 +20,46 @@ namespace ewn
class NavigationComponent : public Ndk::Component<NavigationComponent>
{
public:
using ProximityCallback = std::function<void()>;
struct NavigationResults;

inline NavigationComponent();
~NavigationComponent() = default;

inline void AddImpulse(const Nz::Vector3f& thrust, Nz::UInt64 expirationTime);

inline void ClearTarget();

inline std::pair<Nz::Vector3f /*thrust*/, Nz::Vector3f /*rotation*/> Run(Nz::UInt64 currentTime, float elapsedTime, const Nz::Vector3f& position, const Nz::Quaternionf& rotation, const Nz::Vector3f& linearVel, const Nz::Vector3f& angularVel);
inline NavigationResults Run(Nz::UInt64 currentTime, float elapsedTime, const Nz::Vector3f& position, const Nz::Quaternionf& rotation, const Nz::Vector3f& linearVel, const Nz::Vector3f& angularVel);

inline void SetTarget(const Ndk::EntityHandle& entity);
inline void SetTarget(const Ndk::EntityHandle& entity, float triggerDistance, ProximityCallback proximityCallback);
inline void SetTarget(const Nz::Vector3f& position);
inline void SetTarget(const Nz::Vector3f& position, float triggerDistance, ProximityCallback proximityCallback);

static Ndk::ComponentIndex componentIndex;

struct NavigationResults
{
Nz::Vector3f thrust;
Nz::Vector3f rotation;
bool triggerDistance;
};

private:
std::pair<Nz::Vector3f /*thrust*/, Nz::Vector3f /*rotation*/> ComputeMovement(float elapsedTime, const Nz::Vector3f& position, const Nz::Quaternionf& rotation, const Nz::Vector3f& linearVel, const Nz::Vector3f& angularVel);
NavigationResults ComputeMovement(float elapsedTime, const Nz::Vector3f& position, const Nz::Quaternionf& rotation, const Nz::Vector3f& linearVel, const Nz::Vector3f& angularVel);

struct Impulsion
{
Nz::UInt64 expirationTime;
Nz::Vector3f thrust;
};

ProximityCallback m_proximityCallback;
PidController<Nz::Vector3f> m_headingController;
std::variant<std::monostate, Ndk::EntityHandle, Nz::Vector3f> m_target;
std::vector<Impulsion> m_impulses;
float m_triggerDistance;
};
}

Expand Down
35 changes: 26 additions & 9 deletions src/Server/Components/NavigationComponent.inl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace ewn
m_target = std::monostate();
}

inline std::pair<Nz::Vector3f, Nz::Vector3f> NavigationComponent::Run(Nz::UInt64 currentTime, float elapsedTime, const Nz::Vector3f& position, const Nz::Quaternionf& rotation, const Nz::Vector3f& linearVel, const Nz::Vector3f& angularVel)
inline NavigationComponent::NavigationResults NavigationComponent::Run(Nz::UInt64 currentTime, float elapsedTime, const Nz::Vector3f& position, const Nz::Quaternionf& rotation, const Nz::Vector3f& linearVel, const Nz::Vector3f& angularVel)
{
Nz::Vector3f thrustForce = Nz::Vector3f::Zero();
Nz::Vector3f rotationForce = Nz::Vector3f::Zero();
Expand All @@ -43,13 +43,10 @@ namespace ewn
it = m_impulses.erase(it);
}

if (!std::holds_alternative<std::monostate>(m_target))
{
auto [linearForce, angularForce] = ComputeMovement(elapsedTime, position, rotation, linearVel, angularVel);
auto [linearForce, angularForce, isClose] = ComputeMovement(elapsedTime, position, rotation, linearVel, angularVel);

thrustForce += linearForce;
rotationForce += angularForce;
}
thrustForce += linearForce;
rotationForce += angularForce;

thrustForce.x = Nz::Clamp(thrustForce.x, -1.f, 1.f);
thrustForce.y = Nz::Clamp(thrustForce.y, -1.f, 1.f);
Expand All @@ -58,16 +55,36 @@ namespace ewn
rotationForce.y = Nz::Clamp(rotationForce.y, -1.f, 1.f);
rotationForce.z = Nz::Clamp(rotationForce.z, -1.f, 1.f);

return std::make_pair(thrustForce, rotationForce);
if (isClose && m_proximityCallback)
{
m_proximityCallback();
m_proximityCallback = nullptr;
}

return { thrustForce, rotationForce, isClose };
}

inline void NavigationComponent::SetTarget(const Ndk::EntityHandle & entity)
inline void NavigationComponent::SetTarget(const Ndk::EntityHandle& entity)
{
SetTarget(entity, 0.f, nullptr);
}

inline void NavigationComponent::SetTarget(const Ndk::EntityHandle& entity, float triggerDistance, ProximityCallback proximityCallback)
{
m_target = entity;
m_triggerDistance = triggerDistance;
m_proximityCallback = std::move(proximityCallback);
}

inline void NavigationComponent::SetTarget(const Nz::Vector3f& position)
{
SetTarget(position, 0.f, nullptr);
}

inline void NavigationComponent::SetTarget(const Nz::Vector3f& position, float triggerDistance, ProximityCallback proximityCallback)
{
m_target = position;
m_triggerDistance = triggerDistance;
m_proximityCallback = std::move(proximityCallback);
}
}
81 changes: 44 additions & 37 deletions src/Server/Components/ScriptComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace ewn
{
ScriptComponent::ScriptComponent() :
m_lastMessageTime(0),
m_isInitialized(false)
m_tickCounter(0.f)
{
m_instance.SetMemoryLimit(1'000'000);
m_instance.SetTimeLimit(50);
Expand Down Expand Up @@ -90,45 +90,50 @@ namespace ewn
if (!HasValidScript())
return true;

std::string callbackName;
bool hasParameters = false;

Nz::CallOnExit incrementTickCount([&]()
{
m_tickCounter += elapsedTime;
});

if (m_tickCounter >= 0.5f)
{
callbackName = "OnTick";
hasParameters = true;

m_tickCounter -= 0.5f;
}
else
{
callbackName = m_core->PopCallback().value_or(std::string());
if (callbackName.empty())
return true;
}

incrementTickCount.CallAndReset();

if (m_instance.GetGlobal("Spaceship") == Nz::LuaType_Table)
{
if (m_isInitialized)
{
if (m_instance.GetField("OnTick") == Nz::LuaType_Function)
{
m_instance.PushValue(-2); // Spaceship
m_instance.Push(elapsedTime);
if (!m_instance.Call(2, 0))
{
if (lastError)
*lastError = m_instance.GetLastError();

m_script = Nz::String();
return false;
}
}
else
m_instance.Pop();
}
else
if (m_instance.GetField(callbackName) == Nz::LuaType_Function)
{
m_isInitialized = true;
m_instance.PushValue(-2); // Spaceship

if (hasParameters)
m_instance.Push(0.5f); //< FIXME

if (m_instance.GetField("OnStart") == Nz::LuaType_Function)
if (!m_instance.Call((hasParameters) ? 2 : 1, 0))
{
m_instance.PushValue(-2); // Spaceship
if (!m_instance.Call(1, 0))
{
if (lastError)
*lastError = m_instance.GetLastError();

m_script = Nz::String();
return false;
}
if (lastError)
*lastError = m_instance.GetLastError();

m_script = Nz::String();
return false;
}
else
m_instance.Pop();
}
else
m_instance.Pop();
}
m_instance.Pop();

Expand Down Expand Up @@ -167,16 +172,18 @@ namespace ewn
void ScriptComponent::OnAttached()
{
m_core.emplace(m_entity);
m_core->AddModule(std::make_unique<EngineModule>(m_entity));
m_core->AddModule(std::make_unique<NavigationModule>(m_entity));
m_core->AddModule(std::make_unique<RadarModule>(m_entity));
m_core->AddModule(std::make_unique<WeaponModule>(m_entity));
m_core->AddModule(std::make_shared<EngineModule>(&m_core.value(), m_entity));
m_core->AddModule(std::make_shared<NavigationModule>(&m_core.value(), m_entity));
m_core->AddModule(std::make_shared<RadarModule>(&m_core.value(), m_entity));
m_core->AddModule(std::make_shared<WeaponModule>(&m_core.value(), m_entity));

m_instance.PushTable();
{
m_core->Register(m_instance);
}
m_instance.SetGlobal("Spaceship");

m_core->PushCallback("OnStart");
}

void ScriptComponent::OnDetached()
Expand Down
2 changes: 1 addition & 1 deletion src/Server/Components/ScriptComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace ewn
Nz::UInt64 m_lastMessageTime;
Nz::LuaInstance m_instance;
Nz::String m_script;
bool m_isInitialized;
float m_tickCounter;
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/Server/Modules/EngineModule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace ewn
class EngineModule : public SpaceshipModule, public Nz::HandledObject<EngineModule>
{
public:
inline EngineModule(const Ndk::EntityHandle& spaceship);
using SpaceshipModule::SpaceshipModule;
~EngineModule() = default;

void Impulse(Nz::Vector3f impulse, float duration);
Expand Down
4 changes: 0 additions & 4 deletions src/Server/Modules/EngineModule.inl
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@

namespace ewn
{
inline EngineModule::EngineModule(const Ndk::EntityHandle & spaceship) :
SpaceshipModule(spaceship)
{
}
}

namespace Nz
Expand Down
Loading

0 comments on commit 0f92d21

Please sign in to comment.