Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32f73201c5 | |||
| 3aeeb3cad5 | |||
| 4d5cbb6057 | |||
| db0e67b9bd | |||
| 31e7340daf | |||
| 3ac3311c0c | |||
| 90867b094a | |||
| 55ee2bb3bf | |||
| 406b730ef3 | |||
| b37b20b7d8 | |||
| 750442d224 | |||
| 389e057611 | |||
| 74d9bae896 | |||
| 74c95089ea | |||
| ca2aab449e | |||
| 08c476e9e3 | |||
| 10c3b475bf | |||
| 08fcdb382b | |||
| b1ea5429ce | |||
| fcc9d64e7a | |||
| 7a95880e10 | |||
| 6cd073c3c8 | |||
| 1e3fc1ae2d | |||
| ea9c4d19d0 | |||
| f3bfe388af | |||
| ce27b224df | |||
| f0763bc2a3 | |||
| dbe56280a6 | |||
| c4594524da | |||
| 2a93e2ae7f | |||
| 92553f1e93 | |||
| 7faed50507 | |||
| 6fbb962b5e | |||
| 123c198e19 | |||
| 9bd3da409d | |||
| a8a38716bd | |||
| 8f007f6daf | |||
| 4c2ce3882e | |||
| 7b6902eafe | |||
| 46854a63dd | |||
| dc66891d60 |
+1
-1
Submodule assets updated: 6ffb46e155...e8174f630f
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef EPlayerSpawned_h__
|
||||||
|
#define EPlayerSpawned_h__
|
||||||
|
|
||||||
|
#include "Core/Event.h"
|
||||||
|
#include "Core/EntityWrapper.h"
|
||||||
|
|
||||||
|
namespace Events
|
||||||
|
{
|
||||||
|
|
||||||
|
struct PlayerSpawned : Event
|
||||||
|
{
|
||||||
|
int PlayerID;
|
||||||
|
EntityWrapper Player;
|
||||||
|
EntityWrapper Spawner;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -25,6 +25,8 @@ struct EntityWrapper
|
|||||||
|
|
||||||
bool HasComponent(const std::string& componentName);
|
bool HasComponent(const std::string& componentName);
|
||||||
EntityWrapper Parent();
|
EntityWrapper Parent();
|
||||||
|
EntityWrapper FirstChildByName(const std::string& name);
|
||||||
|
bool IsChildOf(EntityWrapper potentialParent);
|
||||||
bool Valid();
|
bool Valid();
|
||||||
|
|
||||||
ComponentWrapper operator[](const char* componentName);
|
ComponentWrapper operator[](const char* componentName);
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ struct Child
|
|||||||
std::vector<ContainedObject>& m_StaticObjectsRef;
|
std::vector<ContainedObject>& m_StaticObjectsRef;
|
||||||
std::vector<ContainedObject>& m_DynamicObjectsRef;
|
std::vector<ContainedObject>& m_DynamicObjectsRef;
|
||||||
|
|
||||||
inline bool hasChildren() const;
|
bool hasChildren() const;
|
||||||
int childIndexContainingPoint(const glm::vec3& point) const;
|
int childIndexContainingPoint(const glm::vec3& point) const;
|
||||||
std::vector<int> childIndicesContainingBox(const AABB& box) const;
|
std::vector<int> childIndicesContainingBox(const AABB& box) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,13 +3,18 @@
|
|||||||
|
|
||||||
#include "../GLM.h"
|
#include "../GLM.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
#include "EntityWrapper.h"
|
||||||
|
|
||||||
namespace Transform
|
namespace Transform
|
||||||
{
|
{
|
||||||
|
|
||||||
|
glm::vec3 AbsolutePosition(EntityWrapper entity);
|
||||||
glm::vec3 AbsolutePosition(World* world, EntityID entity);
|
glm::vec3 AbsolutePosition(World* world, EntityID entity);
|
||||||
|
glm::quat AbsoluteOrientation(EntityWrapper entity);
|
||||||
glm::quat AbsoluteOrientation(World* world, EntityID entity);
|
glm::quat AbsoluteOrientation(World* world, EntityID entity);
|
||||||
|
glm::vec3 AbsoluteScale(EntityWrapper entity);
|
||||||
glm::vec3 AbsoluteScale(World* world, EntityID entity);
|
glm::vec3 AbsoluteScale(World* world, EntityID entity);
|
||||||
|
glm::mat4 ModelMatrix(EntityWrapper entity);
|
||||||
glm::mat4 ModelMatrix(EntityID entity, World* world);
|
glm::mat4 ModelMatrix(EntityID entity, World* world);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#ifndef EditorCameraInputController_h__
|
||||||
|
#define EditorCameraInputController_h__
|
||||||
|
|
||||||
|
#include <imgui/imgui.h>
|
||||||
|
#include "../Input/FirstPersonInputController.h"
|
||||||
|
#include "../Core/EMousePress.h"
|
||||||
|
#include "../Core/EMouseRelease.h"
|
||||||
|
#include "../Core/EMouseScroll.h"
|
||||||
|
#include "../Core/ConfigFile.h"
|
||||||
|
|
||||||
|
template <typename EventContext>
|
||||||
|
class EditorCameraInputController : public FirstPersonInputController<EventContext>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EditorCameraInputController(EventBroker* eventBroker, unsigned int playerID)
|
||||||
|
: FirstPersonInputController(eventBroker, playerID)
|
||||||
|
{
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorCameraInputController::OnMousePress);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorCameraInputController::OnMouseRelease);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EMouseScroll, &EditorCameraInputController::OnMouseScroll);
|
||||||
|
|
||||||
|
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||||
|
m_SpeedMultiplier = m_Config->Get<float>("Editor.CameraSpeed", 3.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const glm::vec3 Movement() const override { return m_Movement * m_SpeedMultiplier; }
|
||||||
|
|
||||||
|
void Enable() { m_Enabled = true; }
|
||||||
|
void Disable() { m_Enabled = false; }
|
||||||
|
|
||||||
|
virtual bool OnCommand(const Events::InputCommand& e) override
|
||||||
|
{
|
||||||
|
if (glm::abs(e.Value) > 0 && !m_MouseLocked) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (glm::abs(e.Value) > 0 && (io.WantCaptureKeyboard || io.WantCaptureMouse)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Command == "Jump") {
|
||||||
|
if (e.Value > 0) {
|
||||||
|
m_Movement.y = glm::max(e.Value, 1.f);
|
||||||
|
} else {
|
||||||
|
m_Movement.y = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Command == "Crouch") {
|
||||||
|
if (e.Value > 0) {
|
||||||
|
m_Movement.y = glm::min(-e.Value, -1.f);
|
||||||
|
} else {
|
||||||
|
m_Movement.y = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Command == "Sprint") {
|
||||||
|
if (e.Value > 0) {
|
||||||
|
m_SpeedMultiplier *= 2.f;
|
||||||
|
} else {
|
||||||
|
m_SpeedMultiplier /= 2.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FirstPersonInputController::OnCommand(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ConfigFile* m_Config;
|
||||||
|
bool m_Enabled = false;
|
||||||
|
float m_SpeedMultiplier = 1.f;
|
||||||
|
|
||||||
|
EventRelay<EventContext, Events::MousePress> m_EMousePress;
|
||||||
|
bool OnMousePress(const Events::MousePress& e)
|
||||||
|
{
|
||||||
|
if (!m_Enabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Button == GLFW_MOUSE_BUTTON_2) {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (!io.WantCaptureMouse) {
|
||||||
|
LockMouse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EventRelay<EventContext, Events::MouseRelease> m_EMouseRelease;
|
||||||
|
bool OnMouseRelease(const Events::MouseRelease& e)
|
||||||
|
{
|
||||||
|
if (!m_Enabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Button == GLFW_MOUSE_BUTTON_2) {
|
||||||
|
UnlockMouse();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EventRelay<EventContext, Events::MouseScroll> m_EMouseScroll;
|
||||||
|
bool OnMouseScroll(const Events::MouseScroll& e)
|
||||||
|
{
|
||||||
|
if (!m_Enabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_SpeedMultiplier += e.DeltaY * (0.1f * m_SpeedMultiplier);
|
||||||
|
m_Config->Set("Editor.CameraSpeed", m_SpeedMultiplier);
|
||||||
|
m_Config->SaveToDisk();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "../Core/System.h"
|
#include "../Core/System.h"
|
||||||
#include "../Rendering/IRenderer.h"
|
#include "../Rendering/IRenderer.h"
|
||||||
#include "../Rendering/Camera.h"
|
#include "../Rendering/Camera.h"
|
||||||
#include "../Rendering/DebugCameraInputController.h"
|
|
||||||
#include "../Rendering/ESetCamera.h"
|
#include "../Rendering/ESetCamera.h"
|
||||||
#include "../Core/World.h"
|
#include "../Core/World.h"
|
||||||
#include "../Core/SystemPipeline.h"
|
#include "../Core/SystemPipeline.h"
|
||||||
@@ -10,8 +9,10 @@
|
|||||||
#include "../Core/EntityFileParser.h"
|
#include "../Core/EntityFileParser.h"
|
||||||
#include "../Core/EntityFileWriter.h"
|
#include "../Core/EntityFileWriter.h"
|
||||||
#include "../Core/EMousePress.h"
|
#include "../Core/EMousePress.h"
|
||||||
|
#include "../Input/EInputCommand.h"
|
||||||
#include "EditorGUI.h"
|
#include "EditorGUI.h"
|
||||||
#include "EditorStats.h"
|
#include "EditorStats.h"
|
||||||
|
#include "EditorCameraInputController.h"
|
||||||
|
|
||||||
class EditorSystem : public ImpureSystem
|
class EditorSystem : public ImpureSystem
|
||||||
{
|
{
|
||||||
@@ -21,18 +22,24 @@ public:
|
|||||||
|
|
||||||
void Update(double dt);
|
void Update(double dt);
|
||||||
|
|
||||||
|
void Enable();
|
||||||
|
void Disable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IRenderer* m_Renderer;
|
IRenderer* m_Renderer;
|
||||||
RenderFrame* m_RenderFrame;
|
RenderFrame* m_RenderFrame;
|
||||||
World* m_EditorWorld;
|
World* m_EditorWorld;
|
||||||
SystemPipeline* m_EditorWorldSystemPipeline;
|
SystemPipeline* m_EditorWorldSystemPipeline;
|
||||||
Camera* m_EditorCamera;
|
//Camera* m_EditorCamera;
|
||||||
EntityWrapper m_Camera = EntityWrapper::Invalid;
|
EntityWrapper m_EditorCamera = EntityWrapper::Invalid;
|
||||||
DebugCameraInputController<EditorSystem>* m_DebugCameraInputController;
|
EntityWrapper m_ActualCamera = EntityWrapper::Invalid;
|
||||||
|
EditorCameraInputController<EditorSystem>* m_EditorCameraInputController;
|
||||||
EditorGUI* m_EditorGUI;
|
EditorGUI* m_EditorGUI;
|
||||||
EditorStats* m_EditorStats;
|
EditorStats* m_EditorStats;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
double m_LastTime = 0.f;
|
||||||
|
bool m_Enabled = true;
|
||||||
EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate;
|
EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate;
|
||||||
EntityWrapper m_Widget = EntityWrapper::Invalid;
|
EntityWrapper m_Widget = EntityWrapper::Invalid;
|
||||||
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
|
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
|
||||||
@@ -56,4 +63,8 @@ private:
|
|||||||
bool OnMousePress(const Events::MousePress& e);
|
bool OnMousePress(const Events::MousePress& e);
|
||||||
EventRelay<EditorSystem, Events::WidgetDelta> m_EWidgetDelta;
|
EventRelay<EditorSystem, Events::WidgetDelta> m_EWidgetDelta;
|
||||||
bool OnWidgetDelta(const Events::WidgetDelta& e);
|
bool OnWidgetDelta(const Events::WidgetDelta& e);
|
||||||
|
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
|
||||||
|
bool OnInputCommand(const Events::InputCommand& e);
|
||||||
|
EventRelay<EditorSystem, Events::SetCamera> m_ESetCamera;
|
||||||
|
bool OnSetCamera(const Events::SetCamera& e);
|
||||||
};
|
};
|
||||||
@@ -9,7 +9,7 @@ namespace Events
|
|||||||
struct InputCommand : Event
|
struct InputCommand : Event
|
||||||
{
|
{
|
||||||
/** Numerical ID of the player. */
|
/** Numerical ID of the player. */
|
||||||
unsigned int PlayerID;
|
int PlayerID;
|
||||||
/** The command that was sent. */
|
/** The command that was sent. */
|
||||||
std::string Command;
|
std::string Command;
|
||||||
/** The value of the command. */
|
/** The value of the command. */
|
||||||
|
|||||||
@@ -9,62 +9,119 @@ template <typename EventContext>
|
|||||||
class FirstPersonInputController : public InputController<EventContext>
|
class FirstPersonInputController : public InputController<EventContext>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FirstPersonInputController(EventBroker* eventBroker, unsigned int playerID)
|
FirstPersonInputController(EventBroker* eventBroker, int playerID);
|
||||||
: InputController(eventBroker)
|
|
||||||
, m_PlayerID(playerID)
|
|
||||||
{
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse);
|
|
||||||
}
|
|
||||||
|
|
||||||
const glm::quat Orientation() const { return m_Orientation; }
|
virtual const glm::vec3 Movement() const { return m_Movement; }
|
||||||
|
virtual const glm::vec3 Rotation() const { return m_Rotation; }
|
||||||
|
virtual bool Jumping() const { return m_Jumping; }
|
||||||
|
virtual bool Crouching() const { return m_Crouching; }
|
||||||
|
|
||||||
void LockMouse()
|
void LockMouse();
|
||||||
{
|
void UnlockMouse();
|
||||||
Events::LockMouse e;
|
virtual bool OnCommand(const Events::InputCommand& e) override;
|
||||||
m_EventBroker->Publish(e);
|
virtual void Reset();
|
||||||
m_MouseLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnlockMouse()
|
protected:
|
||||||
{
|
const int m_PlayerID;
|
||||||
Events::UnlockMouse e;
|
bool m_MouseLocked = false;
|
||||||
m_EventBroker->Publish(e);
|
glm::vec3 m_Rotation;
|
||||||
m_MouseLocked = false;
|
glm::vec3 m_Movement;
|
||||||
}
|
bool m_Jumping = false;
|
||||||
|
bool m_Crouching = false;
|
||||||
|
|
||||||
virtual bool OnCommand(const Events::InputCommand& e) override
|
EventRelay<EventContext, Events::LockMouse> m_ELockMouse;
|
||||||
{
|
bool OnLockMouse(const Events::LockMouse& e);
|
||||||
if (m_PlayerID != e.PlayerID) {
|
EventRelay<EventContext, Events::UnlockMouse> m_EUnlockMouse;
|
||||||
return false;
|
bool OnUnlockMouse(const Events::UnlockMouse& e);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (m_MouseLocked) {
|
template <typename EventContext>
|
||||||
if (e.Command == "Pitch") {
|
FirstPersonInputController<EventContext>::FirstPersonInputController(EventBroker* eventBroker, int playerID)
|
||||||
float val = glm::radians(e.Value);
|
: InputController(eventBroker)
|
||||||
m_Orientation = m_Orientation * glm::angleAxis<float>(-val, glm::vec3(1, 0, 0));
|
, m_PlayerID(playerID)
|
||||||
return true;
|
{
|
||||||
}
|
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse);
|
||||||
|
}
|
||||||
|
|
||||||
if (e.Command == "Yaw") {
|
template <typename EventContext>
|
||||||
float val = glm::radians(e.Value);
|
void FirstPersonInputController<EventContext>::Reset()
|
||||||
m_Orientation = glm::angleAxis<float>(-val, glm::vec3(0, 1, 0)) * m_Orientation;
|
{
|
||||||
return true;
|
m_Rotation = glm::vec3(0.f, 0.f, 0.f);
|
||||||
}
|
m_Jumping = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename EventContext>
|
||||||
|
void FirstPersonInputController<EventContext>::LockMouse()
|
||||||
|
{
|
||||||
|
Events::LockMouse e;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
m_MouseLocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EventContext>
|
||||||
|
void FirstPersonInputController<EventContext>::UnlockMouse()
|
||||||
|
{
|
||||||
|
Events::UnlockMouse e;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
m_MouseLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EventContext>
|
||||||
|
bool FirstPersonInputController<EventContext>::OnCommand(const Events::InputCommand& e)
|
||||||
|
{
|
||||||
|
if (m_PlayerID != e.PlayerID) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
if (e.Command == "Pitch") {
|
||||||
const unsigned int m_PlayerID;
|
float val = glm::radians(e.Value);
|
||||||
glm::quat m_Orientation;
|
m_Rotation.x += -val;
|
||||||
bool m_MouseLocked = false;
|
//m_Rotation.x = glm::clamp(m_Rotation.x, -glm::half_pi<float>(), glm::half_pi<float>());
|
||||||
|
}
|
||||||
|
|
||||||
EventRelay<EventContext, Events::LockMouse> m_ELockMouse;
|
if (e.Command == "Yaw") {
|
||||||
bool OnLockMouse(const Events::LockMouse& e) { m_MouseLocked = true; return true; }
|
float val = glm::radians(e.Value);
|
||||||
EventRelay<EventContext, Events::UnlockMouse> m_EUnlockMouse;
|
m_Rotation.y += -val;
|
||||||
bool OnUnlockMouse(const Events::UnlockMouse& e) { m_MouseLocked = false; return true; }
|
}
|
||||||
};
|
|
||||||
|
if (e.Command == "Forward" || e.Command == "Right") {
|
||||||
|
if (e.Command == "Forward") {
|
||||||
|
float val = glm::clamp(e.Value, -1.f, 1.f);
|
||||||
|
m_Movement.z = -val;
|
||||||
|
}
|
||||||
|
if (e.Command == "Right") {
|
||||||
|
float val = glm::clamp(e.Value, -1.f, 1.f);
|
||||||
|
m_Movement.x = val;
|
||||||
|
}
|
||||||
|
if (glm::length2(m_Movement) > 0) {
|
||||||
|
m_Movement = glm::normalize(m_Movement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Command == "Jump") {
|
||||||
|
m_Jumping = e.Value > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Command == "Crouch") {
|
||||||
|
m_Crouching = e.Value > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EventContext>
|
||||||
|
bool FirstPersonInputController<EventContext>::OnUnlockMouse(const Events::UnlockMouse& e)
|
||||||
|
{
|
||||||
|
m_MouseLocked = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EventContext>
|
||||||
|
bool FirstPersonInputController<EventContext>::OnLockMouse(const Events::LockMouse& e)
|
||||||
|
{
|
||||||
|
m_MouseLocked = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "Input/EInputCommand.h"
|
#include "Input/EInputCommand.h"
|
||||||
#include "Core/EPlayerDamage.h"
|
#include "Core/EPlayerDamage.h"
|
||||||
#include "Network/EInterpolate.h"
|
#include "Network/EInterpolate.h"
|
||||||
|
#include "Core/EPlayerSpawned.h"
|
||||||
|
|
||||||
class Client : public Network
|
class Client : public Network
|
||||||
{
|
{
|
||||||
@@ -39,14 +40,14 @@ private:
|
|||||||
char readBuf[INPUTSIZE] = { 0 };
|
char readBuf[INPUTSIZE] = { 0 };
|
||||||
|
|
||||||
// Packet loss logic
|
// Packet loss logic
|
||||||
unsigned int m_PacketID = 0;
|
PacketID m_PacketID = 0;
|
||||||
unsigned int m_PreviousPacketID = 0;
|
PacketID m_PreviousPacketID = 0;
|
||||||
unsigned int m_SendPacketID = 0;
|
PacketID m_SendPacketID = 0;
|
||||||
|
|
||||||
// Game logic
|
// Game logic
|
||||||
World* m_World;
|
World* m_World;
|
||||||
std::string m_PlayerName;
|
std::string m_PlayerName;
|
||||||
int m_PlayerID = -1;
|
PlayerID m_PlayerID = -1;
|
||||||
EntityID m_ServerEntityID = std::numeric_limits<EntityID>::max();
|
EntityID m_ServerEntityID = std::numeric_limits<EntityID>::max();
|
||||||
bool m_IsConnected = false;
|
bool m_IsConnected = false;
|
||||||
// Server Client Lookup map
|
// Server Client Lookup map
|
||||||
@@ -57,25 +58,27 @@ private:
|
|||||||
std::unordered_map<EntityID, EntityID> m_ClientIDToServerID;
|
std::unordered_map<EntityID, EntityID> m_ClientIDToServerID;
|
||||||
|
|
||||||
// Network logic
|
// Network logic
|
||||||
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
|
PlayerDefinition m_PlayerDefinitions[8];
|
||||||
SnapshotDefinitions m_NextSnapshot;
|
SnapshotDefinitions m_NextSnapshot;
|
||||||
double m_DurationOfPingTime;
|
double m_DurationOfPingTime;
|
||||||
std::clock_t m_StartPingTime;
|
std::clock_t m_StartPingTime;
|
||||||
|
std::clock_t m_TimeSinceSentInputs;
|
||||||
|
unsigned int m_SendInputIntervalMs;
|
||||||
std::vector<Events::InputCommand> m_InputCommandBuffer;
|
std::vector<Events::InputCommand> m_InputCommandBuffer;
|
||||||
|
|
||||||
// Private member functions
|
// Private member functions
|
||||||
void readFromServer();
|
void readFromServer();
|
||||||
int receive(char* data, size_t length);
|
int receive(char* data);
|
||||||
void send(Packet& packet);
|
void send(Packet& packet);
|
||||||
void connect();
|
void connect();
|
||||||
void disconnect();
|
void disconnect();
|
||||||
void ping();
|
|
||||||
void parseMessageType(Packet& packet);
|
void parseMessageType(Packet& packet);
|
||||||
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType);
|
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType);
|
||||||
void parseConnect(Packet& packet);
|
void parseConnect(Packet& packet);
|
||||||
void parsePlayerConnected(Packet& packet);
|
void parsePlayerConnected(Packet& packet);
|
||||||
void parsePing();
|
void parsePing();
|
||||||
void parseServerPing();
|
void parseKick();
|
||||||
|
void parsePlayersSpawned(Packet& packet);
|
||||||
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
|
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
|
||||||
void parseSnapshot(Packet& packet);
|
void parseSnapshot(Packet& packet);
|
||||||
void identifyPacketLoss();
|
void identifyPacketLoss();
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef Events_PlayerDisconnected
|
||||||
|
#define Events_PlayerDisconnected
|
||||||
|
|
||||||
|
#include "Core/EventBroker.h"
|
||||||
|
#include "Core/Entity.h"
|
||||||
|
|
||||||
|
namespace Events
|
||||||
|
{
|
||||||
|
|
||||||
|
struct PlayerDisconnected : public Event
|
||||||
|
{
|
||||||
|
unsigned int PlayerID;
|
||||||
|
EntityID Entity;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,16 +5,17 @@
|
|||||||
// Used to determine what type of message was sent.
|
// Used to determine what type of message was sent.
|
||||||
enum class MessageType
|
enum class MessageType
|
||||||
{
|
{
|
||||||
Connect,
|
Connect,
|
||||||
Disconnect,
|
Disconnect,
|
||||||
ClientPing,
|
Ping,
|
||||||
ServerPing,
|
Message,
|
||||||
Message,
|
Snapshot,
|
||||||
Snapshot,
|
|
||||||
OnInputCommand,
|
OnInputCommand,
|
||||||
OnPlayerDamage,
|
OnPlayerDamage,
|
||||||
PlayerConnected,
|
PlayerConnected,
|
||||||
BecomePlayer
|
BecomePlayer,
|
||||||
|
Kick,
|
||||||
|
OnPlayerSpawned
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
#ifndef Network_h__
|
#ifndef Network_h__
|
||||||
#define Network_h__
|
#define Network_h__
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
#include "Core/World.h"
|
#include "Core/World.h"
|
||||||
#include "Core/EventBroker.h"
|
#include "Core/EventBroker.h"
|
||||||
#include "Network/Packet.h"
|
#include "Network/Packet.h"
|
||||||
|
#include "Network/NetworkData.h"
|
||||||
|
#include "Core/ResourceManager.h"
|
||||||
|
#include "Core/ConfigFile.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#define MAXCONNECTIONS 8
|
|
||||||
#define INPUTSIZE 4097
|
#define INPUTSIZE 4097
|
||||||
#define TIMEOUTMS 15000
|
typedef unsigned int PlayerID;
|
||||||
|
typedef unsigned int PacketID;
|
||||||
|
typedef unsigned int UserID;
|
||||||
|
|
||||||
class Network
|
class Network
|
||||||
{
|
{
|
||||||
@@ -15,6 +23,17 @@ public:
|
|||||||
virtual ~Network() { };
|
virtual ~Network() { };
|
||||||
virtual void Start(World* m_world, EventBroker *eventBroker) = 0;
|
virtual void Start(World* m_world, EventBroker *eventBroker) = 0;
|
||||||
virtual void Update() = 0;
|
virtual void Update() = 0;
|
||||||
|
protected:
|
||||||
|
// For Debug
|
||||||
|
bool isReadingData = false;
|
||||||
|
NetworkData m_NetworkData;
|
||||||
|
unsigned int m_SaveDataIntervalMs = 1000;
|
||||||
|
std::clock_t m_SaveDataTimer;
|
||||||
|
unsigned int m_MaxConnections;
|
||||||
|
unsigned int m_TimeoutMs;
|
||||||
|
void saveToFile();
|
||||||
|
void updateNetworkData();
|
||||||
|
void initialize();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef NetworkData_h__
|
||||||
|
#define NetworkData_h__
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct NetworkData {
|
||||||
|
unsigned int TotalTime = 0;
|
||||||
|
unsigned int TotalDataReceived = 0;
|
||||||
|
unsigned int TotalDataSent = 0;
|
||||||
|
unsigned int AmountOfMessagesReceived = 0;
|
||||||
|
unsigned int AmountOfMessagesSent = 0;
|
||||||
|
// Interval based
|
||||||
|
unsigned int DataReceivedThisInterval = 0;
|
||||||
|
unsigned int DataSentThisInterval = 0;
|
||||||
|
// pair: first=reveived, second=send
|
||||||
|
std::vector<std::pair<unsigned int, unsigned int>> BandwidthBytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -55,12 +55,14 @@ public:
|
|||||||
char* Data() { return m_Data; };
|
char* Data() { return m_Data; };
|
||||||
unsigned int DataReadSize() { return m_ReturnDataOffset; }
|
unsigned int DataReadSize() { return m_ReturnDataOffset; }
|
||||||
unsigned int MaxSize() { return m_MaxPacketSize; }
|
unsigned int MaxSize() { return m_MaxPacketSize; }
|
||||||
|
unsigned int HeaderSize() { return m_HeaderSize; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* m_Data;
|
char* m_Data;
|
||||||
unsigned int m_ReturnDataOffset = 0;
|
unsigned int m_ReturnDataOffset = 0;
|
||||||
int m_Offset = 0;
|
int m_Offset = 0;
|
||||||
unsigned int m_MaxPacketSize = 512;
|
unsigned int m_MaxPacketSize = 512;
|
||||||
|
unsigned int m_HeaderSize = 0;
|
||||||
void resizeData();
|
void resizeData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include "../Network/Network.h"
|
#include "../Network/Network.h"
|
||||||
#include "Input/EInputCommand.h"
|
#include "Input/EInputCommand.h"
|
||||||
#include "Core/EPlayerDamage.h"
|
#include "Core/EPlayerDamage.h"
|
||||||
|
#include "Network/EPlayerDisconnected.h"
|
||||||
|
#include "Core/EPlayerSpawned.h"
|
||||||
|
|
||||||
class Server : public Network
|
class Server : public Network
|
||||||
{
|
{
|
||||||
@@ -29,7 +31,7 @@ private:
|
|||||||
boost::asio::ip::udp::socket m_Socket;
|
boost::asio::ip::udp::socket m_Socket;
|
||||||
|
|
||||||
// Sending messages to client logic
|
// Sending messages to client logic
|
||||||
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
|
PlayerDefinition m_PlayerDefinitions[8]; //
|
||||||
std::vector<PlayerDefinition> m_ConnectedUsers;
|
std::vector<PlayerDefinition> m_ConnectedUsers;
|
||||||
char readBuffer[INPUTSIZE] = { 0 };
|
char readBuffer[INPUTSIZE] = { 0 };
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
@@ -38,8 +40,8 @@ private:
|
|||||||
std::clock_t previousSnapshotMessage = std::clock();
|
std::clock_t previousSnapshotMessage = std::clock();
|
||||||
std::clock_t timOutTimer = std::clock();
|
std::clock_t timOutTimer = std::clock();
|
||||||
// How often we send messages (milliseconds)
|
// How often we send messages (milliseconds)
|
||||||
int intervalMs = 1000;
|
int pingIntervalMs;
|
||||||
int snapshotInterval = 50;
|
int snapshotInterval;
|
||||||
int checkTimeOutInterval = 100;
|
int checkTimeOutInterval = 100;
|
||||||
|
|
||||||
//Timers
|
//Timers
|
||||||
@@ -50,32 +52,36 @@ private:
|
|||||||
EventBroker* m_EventBroker;
|
EventBroker* m_EventBroker;
|
||||||
|
|
||||||
// Packet loss logic
|
// Packet loss logic
|
||||||
unsigned int m_PacketID = 0;
|
PacketID m_PacketID = 0;
|
||||||
unsigned int m_PreviousPacketID = 0;
|
PacketID m_PreviousPacketID = 0;
|
||||||
|
|
||||||
// Private member functions
|
// Private member functions
|
||||||
int receive(char* data, size_t length);
|
int receive(char* data);
|
||||||
void readFromClients();
|
void readFromClients();
|
||||||
void send(Packet& packet, int playerID);
|
void send(Packet& packet, UserID user);
|
||||||
|
void send(PlayerID player, Packet& packet);
|
||||||
void send(Packet& packet);
|
void send(Packet& packet);
|
||||||
void broadcast(Packet& packet);
|
void broadcast(Packet& packet);
|
||||||
void sendSnapshot();
|
void sendSnapshot();
|
||||||
void sendPing();
|
void sendPing();
|
||||||
void checkForTimeOuts();
|
void checkForTimeOuts();
|
||||||
void disconnect(int i);
|
void disconnect(UserID user);
|
||||||
void parseMessageType(Packet& packet);
|
void parseMessageType(Packet& packet);
|
||||||
void parseOnInputCommand(Packet& packet);
|
void parseOnInputCommand(Packet& packet);
|
||||||
void parseOnPlayerDamage(Packet& packet);
|
void parseOnPlayerDamage(Packet& packet);
|
||||||
void parseConnect(Packet& packet);
|
void parseConnect(Packet& packet);
|
||||||
void parseDisconnect();
|
void parseDisconnect();
|
||||||
void parseClientPing();
|
void parseClientPing();
|
||||||
void parseServerPing();
|
void parsePing();
|
||||||
void identifyPacketLoss();
|
void identifyPacketLoss();
|
||||||
void createPlayer();
|
void createPlayer();
|
||||||
int GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint);
|
void kick(PlayerID player);
|
||||||
|
PlayerID GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint);
|
||||||
// Debug event
|
// Debug event
|
||||||
EventRelay<Server, Events::InputCommand> m_EInputCommand;
|
EventRelay<Server, Events::InputCommand> m_EInputCommand;
|
||||||
bool OnInputCommand(const Events::InputCommand& e);
|
bool OnInputCommand(const Events::InputCommand& e);
|
||||||
|
EventRelay<Server, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||||
|
bool OnPlayerSpawned(const Events::PlayerSpawned& e);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
#ifndef DebugCameraInputController_h__
|
|
||||||
#define DebugCameraInputController_h__
|
|
||||||
|
|
||||||
#include <imgui/imgui.h>
|
|
||||||
#include "../Input/FirstPersonInputController.h"
|
|
||||||
#include "../Core/EMousePress.h"
|
|
||||||
#include "../Core/EMouseRelease.h"
|
|
||||||
|
|
||||||
template <typename EventContext>
|
|
||||||
class DebugCameraInputController : public FirstPersonInputController<EventContext>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DebugCameraInputController(EventBroker* eventBroker, unsigned int playerID)
|
|
||||||
: FirstPersonInputController(eventBroker, playerID)
|
|
||||||
{
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &DebugCameraInputController::OnMousePress);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &DebugCameraInputController::OnMouseRelease);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPosition(const glm::vec3 position) { m_Position = position; }
|
|
||||||
void SetOrientation(const glm::quat orientation) { m_Orientation = orientation; }
|
|
||||||
|
|
||||||
const glm::vec3 Position() const { return m_Position; }
|
|
||||||
void SetBaseSpeed(float speed) { m_BaseSpeed = speed; }
|
|
||||||
|
|
||||||
virtual bool OnCommand(const Events::InputCommand& e) override
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
if (!io.WantCaptureKeyboard) {
|
|
||||||
if (e.Command == "Right") {
|
|
||||||
float value = std::max(-1.f, std::min(e.Value, 1.f));
|
|
||||||
m_Velocity.x = value;
|
|
||||||
}
|
|
||||||
if (e.Command == "Forward") {
|
|
||||||
float value = std::max(-1.f, std::min(e.Value, 1.f));
|
|
||||||
m_Velocity.z = -value;
|
|
||||||
}
|
|
||||||
if (e.Command == "Sprint") {
|
|
||||||
if (e.Value > 0.f) {
|
|
||||||
m_Speed = m_BaseSpeed * 2.f * (e.Value);
|
|
||||||
} else {
|
|
||||||
m_Speed = m_BaseSpeed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FirstPersonInputController::OnCommand(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update(double dt)
|
|
||||||
{
|
|
||||||
if (glm::length2(m_Velocity) > 0) {
|
|
||||||
m_Position += m_Orientation * (glm::normalize(m_Velocity) * m_Speed * (float)dt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
glm::vec3 m_Position = glm::vec3(0, 0, 0);
|
|
||||||
glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
|
|
||||||
float m_BaseSpeed = 2.0f;
|
|
||||||
float m_Speed = m_BaseSpeed;
|
|
||||||
EventRelay<EventContext, Events::MousePress> m_EMousePress;
|
|
||||||
bool OnMousePress(const Events::MousePress& e)
|
|
||||||
{
|
|
||||||
if (e.Button == GLFW_MOUSE_BUTTON_2) {
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
if (!io.WantCaptureMouse) {
|
|
||||||
LockMouse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
EventRelay<EventContext, Events::MouseRelease> m_EMouseRelease;
|
|
||||||
bool OnMouseRelease(const Events::MouseRelease& e)
|
|
||||||
{
|
|
||||||
if (e.Button == GLFW_MOUSE_BUTTON_2) {
|
|
||||||
UnlockMouse();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef Font_h__
|
||||||
|
#define Font_h__
|
||||||
|
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_GLYPH_H
|
||||||
|
#include <boost/tokenizer.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include "../OpenGL.h"
|
||||||
|
#include "../GLM.h"
|
||||||
|
#include "../Core/ResourceManager.h"
|
||||||
|
|
||||||
|
class Font : public Resource
|
||||||
|
{
|
||||||
|
friend class ResourceManager;
|
||||||
|
private:
|
||||||
|
Font(std::string path);
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Character {
|
||||||
|
GLuint TextureID; // ID handle of the glyph texture
|
||||||
|
glm::ivec2 Size; // Size of glyph
|
||||||
|
glm::ivec2 Bearing; // Offset from baseline to left/top of glyph
|
||||||
|
GLuint Advance; // Offset to advance to next glyph
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int FontSize = 16;
|
||||||
|
|
||||||
|
~Font();
|
||||||
|
|
||||||
|
std::map<GLchar, Character> m_Characters;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
@@ -11,49 +11,16 @@
|
|||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "RenderJob.h"
|
#include "RenderJob.h"
|
||||||
#include "ModelJob.h"
|
#include "ModelJob.h"
|
||||||
|
#include "TextJob.h"
|
||||||
#include "PointLightJob.h"
|
#include "PointLightJob.h"
|
||||||
#include "DirectionalLightJob.h"
|
#include "DirectionalLightJob.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
struct SpriteJob : RenderJob
|
|
||||||
{
|
|
||||||
unsigned int ShaderID = 0;
|
|
||||||
unsigned int TextureID = 0;
|
|
||||||
|
|
||||||
glm::mat4 ModelMatrix;
|
|
||||||
const Texture* DiffuseTexture = nullptr;
|
|
||||||
const Texture* NormalTexture = nullptr;
|
|
||||||
const Texture* SpecularTexture = nullptr;
|
|
||||||
glm::vec4 Color;
|
|
||||||
|
|
||||||
void CalculateHash() override
|
|
||||||
{
|
|
||||||
Hash = TextureID;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PointLightJob : RenderJob
|
|
||||||
{
|
|
||||||
glm::vec4 Position;
|
|
||||||
glm::vec4 Color;
|
|
||||||
float Radius;
|
|
||||||
float Intensity;
|
|
||||||
float Falloff;
|
|
||||||
float padding = 123;
|
|
||||||
|
|
||||||
void CalculateHash() override
|
|
||||||
{
|
|
||||||
Hash = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct RenderScene
|
struct RenderScene
|
||||||
{
|
{
|
||||||
::Camera* Camera = nullptr;
|
::Camera* Camera = nullptr;
|
||||||
std::list<std::shared_ptr<RenderJob>> ForwardJobs;
|
std::list<std::shared_ptr<RenderJob>> ForwardJobs;
|
||||||
std::list<std::shared_ptr<RenderJob>> PointLightJobs;
|
std::list<std::shared_ptr<RenderJob>> PointLightJobs;
|
||||||
|
std::list<std::shared_ptr<RenderJob>> TextJobs;
|
||||||
std::list<std::shared_ptr<RenderJob>> DirectionalLightJobs;
|
std::list<std::shared_ptr<RenderJob>> DirectionalLightJobs;
|
||||||
Rectangle Viewport;
|
Rectangle Viewport;
|
||||||
bool ClearDepth = false;
|
bool ClearDepth = false;
|
||||||
@@ -62,6 +29,7 @@ struct RenderScene
|
|||||||
{
|
{
|
||||||
ForwardJobs.clear();
|
ForwardJobs.clear();
|
||||||
PointLightJobs.clear();
|
PointLightJobs.clear();
|
||||||
|
TextJobs.clear();
|
||||||
DirectionalLightJobs.clear();
|
DirectionalLightJobs.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -98,5 +66,4 @@ public:
|
|||||||
private:
|
private:
|
||||||
int m_Size = 0;
|
int m_Size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "PointLightJob.h"
|
#include "PointLightJob.h"
|
||||||
#include "../Core/Transform.h"
|
#include "../Core/Transform.h"
|
||||||
#include "DebugCameraInputController.h"
|
#include "../Core/EPlayerSpawned.h"
|
||||||
|
|
||||||
class RenderSystem : public ImpureSystem
|
class RenderSystem : public ImpureSystem
|
||||||
{
|
{
|
||||||
@@ -30,9 +30,11 @@ private:
|
|||||||
RenderFrame* m_RenderFrame;
|
RenderFrame* m_RenderFrame;
|
||||||
Camera* m_Camera;
|
Camera* m_Camera;
|
||||||
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
|
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
|
||||||
|
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||||
|
|
||||||
EventRelay<RenderSystem, Events::SetCamera> m_ESetCamera;
|
EventRelay<RenderSystem, Events::SetCamera> m_ESetCamera;
|
||||||
bool OnSetCamera(Events::SetCamera &event);
|
bool OnSetCamera(Events::SetCamera &event);
|
||||||
|
void fillText(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
|
||||||
void fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
|
void fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
|
||||||
void fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
|
void fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
|
||||||
EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand;
|
EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand;
|
||||||
@@ -40,6 +42,9 @@ private:
|
|||||||
|
|
||||||
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs);
|
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs);
|
||||||
void fillLight(std::list<std::shared_ptr<RenderJob>>& jobs);
|
void fillLight(std::list<std::shared_ptr<RenderJob>>& jobs);
|
||||||
|
|
||||||
|
EventRelay<RenderSystem, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||||
|
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "../Core/Transform.h"
|
#include "../Core/Transform.h"
|
||||||
|
|
||||||
|
#include "TextRenderer.h"
|
||||||
|
|
||||||
class Renderer : public IRenderer
|
class Renderer : public IRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -34,6 +36,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
//----------------------Variables----------------------//
|
//----------------------Variables----------------------//
|
||||||
EventBroker* m_EventBroker;
|
EventBroker* m_EventBroker;
|
||||||
|
TextRenderer* m_TextRenderer;
|
||||||
|
|
||||||
Texture* m_ErrorTexture;
|
Texture* m_ErrorTexture;
|
||||||
Texture* m_WhiteTexture;
|
Texture* m_WhiteTexture;
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef TextJob_h__
|
||||||
|
#define TextJob_h__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "../Common.h"
|
||||||
|
#include "../GLM.h"
|
||||||
|
#include "../Core/ComponentWrapper.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
#include "RenderJob.h"
|
||||||
|
#include "../Core/ResourceManager.h"
|
||||||
|
#include "Font.h"
|
||||||
|
|
||||||
|
struct TextJob : RenderJob
|
||||||
|
{
|
||||||
|
TextJob(glm::mat4 matrix, Font* font, ComponentWrapper textComponent)
|
||||||
|
: RenderJob()
|
||||||
|
{
|
||||||
|
Matrix = matrix;
|
||||||
|
Color = (glm::vec4)textComponent["Color"];
|
||||||
|
Content = (std::string)textComponent["Content"];
|
||||||
|
Resource = font;
|
||||||
|
|
||||||
|
if ((int)textComponent["Alignment"] == textComponent["Alignment"].Enum("Left")) {
|
||||||
|
Alignment = AlignmentEnum::Left;
|
||||||
|
} else if ((int)textComponent["Alignment"] == textComponent["Alignment"].Enum("Right")) {
|
||||||
|
Alignment = AlignmentEnum::Right;
|
||||||
|
} else if ((int)textComponent["Alignment"] == textComponent["Alignment"].Enum("Center")) {
|
||||||
|
Alignment = AlignmentEnum::Center;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Text alignment invalid");
|
||||||
|
Alignment = AlignmentEnum::Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AlignmentEnum
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Center
|
||||||
|
};
|
||||||
|
|
||||||
|
glm::mat4 Matrix;
|
||||||
|
glm::vec4 Color;
|
||||||
|
std::string Content;
|
||||||
|
Font* Resource;
|
||||||
|
AlignmentEnum Alignment;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void CalculateHash() override
|
||||||
|
{
|
||||||
|
Hash = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef TextRenderer_h__
|
||||||
|
#define TextRenderer_h__
|
||||||
|
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
#include "../OpenGL.h"
|
||||||
|
#include "../GLM.h"
|
||||||
|
#include "ShaderProgram.h"
|
||||||
|
#include "Font.h"
|
||||||
|
#include "../Core/ResourceManager.h"
|
||||||
|
#include "RenderQueue.h"
|
||||||
|
|
||||||
|
class TextRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextRenderer();
|
||||||
|
void Initialize();
|
||||||
|
void Update();
|
||||||
|
void Draw(RenderScene& scene);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void renderText(std::string text, Font* font, TextJob::AlignmentEnum alignment, glm::vec4 color, glm::mat4 modelMatrix, glm::mat4 projectionMatrix, glm::mat4 viewMatrix);
|
||||||
|
|
||||||
|
Font* font;
|
||||||
|
GLuint VAO, VBO;
|
||||||
|
ShaderProgram* m_TextProgram;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
void Bind(GLenum textureUnit = GL_TEXTURE0);
|
void Bind(GLenum textureUnit = GL_TEXTURE0);
|
||||||
|
|
||||||
GLuint m_Texture = 0;
|
GLuint m_Texture = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "Rendering/RenderSystem.h"
|
#include "Rendering/RenderSystem.h"
|
||||||
#include "Core/EntityFileParser.h"
|
#include "Core/EntityFileParser.h"
|
||||||
#include "Core/Octree.h"
|
#include "Core/Octree.h"
|
||||||
|
#include "Rendering/Font.h"
|
||||||
#include "Systems/InterpolationSystem.h"
|
#include "Systems/InterpolationSystem.h"
|
||||||
// Network
|
// Network
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|||||||
@@ -10,11 +10,12 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
#include "Core/EventBroker.h"
|
#include "Core/EventBroker.h"
|
||||||
|
#include "Core/ResourceManager.h"
|
||||||
|
#include "Core/ConfigFile.h"
|
||||||
|
#include "Core/EPlayerSpawned.h"
|
||||||
|
|
||||||
#include "Network/EInterpolate.h"
|
#include "Network/EInterpolate.h"
|
||||||
|
|
||||||
#define SNAPSHOTINTERVAL 0.05f
|
|
||||||
|
|
||||||
class InterpolationSystem : public PureSystem
|
class InterpolationSystem : public PureSystem
|
||||||
{
|
{
|
||||||
struct Transform
|
struct Transform
|
||||||
@@ -25,29 +26,28 @@ class InterpolationSystem : public PureSystem
|
|||||||
double interpolationTime;
|
double interpolationTime;
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
InterpolationSystem(World* world, EventBroker* eventBroker)
|
InterpolationSystem(World* world, EventBroker* eventBroker);
|
||||||
: System(world, eventBroker)
|
|
||||||
, PureSystem("Transform")
|
|
||||||
{
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate);
|
|
||||||
}
|
|
||||||
~InterpolationSystem() { }
|
~InterpolationSystem() { }
|
||||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override;
|
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override;
|
||||||
private:
|
private:
|
||||||
std::unordered_map<EntityID, Transform> m_NextTransform;
|
std::unordered_map<EntityID, Transform> m_NextTransform;
|
||||||
std::unordered_map<EntityID, Transform> m_LastReceivedTransform;
|
std::unordered_map<EntityID, Transform> m_LastReceivedTransform;
|
||||||
|
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||||
|
|
||||||
//glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime);
|
//glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T vectorInterpolation(T prev, T next, double currentTime)
|
T vectorInterpolation(T prev, T next, double currentTime)
|
||||||
{
|
{
|
||||||
T difference = next - prev;
|
T difference = next - prev;
|
||||||
T vector = (difference / SNAPSHOTINTERVAL) * static_cast<float>(currentTime);
|
T vector = (difference / m_SnapshotInterval) * static_cast<float>(currentTime);
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
float m_SnapshotInterval;
|
||||||
|
|
||||||
EventRelay<InterpolationSystem, Events::Interpolate> m_EInterpolate;
|
EventRelay<InterpolationSystem, Events::Interpolate> m_EInterpolate;
|
||||||
bool InterpolationSystem::OnInterpolate(const Events::Interpolate& e);
|
bool InterpolationSystem::OnInterpolate(const Events::Interpolate& e);
|
||||||
|
EventRelay<InterpolationSystem, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||||
|
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "GLM.h"
|
#include "GLM.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
#include "Core/EPlayerSpawned.h"
|
||||||
|
#include "Input/FirstPersonInputController.h"
|
||||||
|
|
||||||
class PlayerMovementSystem : public PureSystem
|
class PlayerMovementSystem : public ImpureSystem, PureSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlayerMovementSystem(World* world, EventBroker* eventBroker)
|
PlayerMovementSystem(World* world, EventBroker* eventBroker);
|
||||||
: System(world, eventBroker)
|
~PlayerMovementSystem();
|
||||||
, PureSystem("Player")
|
|
||||||
{ }
|
|
||||||
|
|
||||||
|
virtual void Update(double dt) override;
|
||||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt);
|
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// State
|
||||||
|
std::unordered_map<EntityWrapper, FirstPersonInputController<PlayerMovementSystem>*> m_PlayerInputControllers;
|
||||||
|
|
||||||
|
EventRelay<PlayerMovementSystem, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||||
|
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||||
};
|
};
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
#include "Input/EInputCommand.h"
|
#include "Input/EInputCommand.h"
|
||||||
#include "Systems/SpawnerSystem.h"
|
#include "Systems/SpawnerSystem.h"
|
||||||
#include "Events/ESpawnerSpawn.h"
|
#include "Events/ESpawnerSpawn.h"
|
||||||
|
#include "Core/EPlayerSpawned.h"
|
||||||
|
#include "Rendering/ESetCamera.h"
|
||||||
|
#include "Core/ConfigFile.h"
|
||||||
|
|
||||||
class PlayerSpawnSystem : public ImpureSystem
|
class PlayerSpawnSystem : public ImpureSystem
|
||||||
{
|
{
|
||||||
@@ -11,8 +14,17 @@ public:
|
|||||||
virtual void Update(double dt) override;
|
virtual void Update(double dt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct SpawnRequest
|
||||||
|
{
|
||||||
|
int PlayerID;
|
||||||
|
ComponentInfo::EnumType Team;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool m_NetworkEnabled = false;
|
||||||
|
std::vector<SpawnRequest> m_SpawnRequests;
|
||||||
|
|
||||||
EventRelay<PlayerSpawnSystem, Events::InputCommand> m_OnInputCommand;
|
EventRelay<PlayerSpawnSystem, Events::InputCommand> m_OnInputCommand;
|
||||||
bool OnInputCommand(const Events::InputCommand& e);
|
bool OnInputCommand(const Events::InputCommand& e);
|
||||||
|
EventRelay<PlayerSpawnSystem, Events::PlayerSpawned> m_OnPlayerSpawnerd;
|
||||||
std::vector<int> m_SpawnRequests;
|
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||||
};
|
};
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
[Debug]
|
[Debug]
|
||||||
LogLevel=1
|
LogLevel=1
|
||||||
LoadMap=
|
LoadMap=
|
||||||
EditorEnabled=false
|
|
||||||
; if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
|
; if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
|
||||||
; if false -> Use pool allocation.
|
; if false -> Use pool allocation.
|
||||||
DisableMemoryPool=false
|
DisableMemoryPool=false
|
||||||
|
|
||||||
|
[Editor]
|
||||||
|
CameraSpeed=3
|
||||||
|
|
||||||
[Video]
|
[Video]
|
||||||
Fullscreen=false
|
Fullscreen=false
|
||||||
VSYNC=false
|
VSYNC=false
|
||||||
@@ -19,6 +21,11 @@ IsServer=false
|
|||||||
Name=Bob
|
Name=Bob
|
||||||
Address=127.0.0.1
|
Address=127.0.0.1
|
||||||
Port=13
|
Port=13
|
||||||
|
MaxConnections=8
|
||||||
|
SnapshotInterval=0.05
|
||||||
|
SendInputIntervalMs=33
|
||||||
|
PingIntervalMs= 1000
|
||||||
|
TimeoutMs=15000
|
||||||
|
|
||||||
[Multithreading]
|
[Multithreading]
|
||||||
ResourceLoading=true
|
ResourceLoading=true
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<xs:include schemaLocation="Components/Model.xsd"/>
|
<xs:include schemaLocation="Components/Model.xsd"/>
|
||||||
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
|
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
|
||||||
<xs:include schemaLocation="Components/Player.xsd"/>
|
<xs:include schemaLocation="Components/Player.xsd"/>
|
||||||
|
<xs:include schemaLocation="Components/Text.xsd"/>
|
||||||
<xs:include schemaLocation="Components/Camera.xsd"/>
|
<xs:include schemaLocation="Components/Camera.xsd"/>
|
||||||
<xs:include schemaLocation="Components/AABB.xsd"/>
|
<xs:include schemaLocation="Components/AABB.xsd"/>
|
||||||
<xs:include schemaLocation="Components/PointLight.xsd"/>
|
<xs:include schemaLocation="Components/PointLight.xsd"/>
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
<Player xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Player.xsd">
|
<Player xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Player.xsd">
|
||||||
<Velocity X="0" Y="0" Z="0"/>
|
<MovementSpeed>0.2</MovementSpeed>
|
||||||
<Forward>false</Forward>
|
|
||||||
<Left>false</Left>
|
|
||||||
<Back>false</Back>
|
|
||||||
<Right>false</Right>
|
|
||||||
</Player>
|
</Player>
|
||||||
@@ -9,11 +9,7 @@
|
|||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:all>
|
<xs:all>
|
||||||
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
|
<xs:element name="MovementSpeed" type="t:float" minOccurs="0"/>
|
||||||
<xs:element name="Forward" type="t:bool" minOccurs="0"/>
|
|
||||||
<xs:element name="Left" type="t:bool" minOccurs="0"/>
|
|
||||||
<xs:element name="Back" type="t:bool" minOccurs="0"/>
|
|
||||||
<xs:element name="Right" type="t:bool" minOccurs="0"/>
|
|
||||||
</xs:all>
|
</xs:all>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<Text xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Text.xsd">
|
||||||
|
<Content>Text</Content>
|
||||||
|
<Resource></Resource>
|
||||||
|
<Color R="1" G="1" B="1" A="1"/>
|
||||||
|
<Visible>true</Visible>
|
||||||
|
<Alignment><Center/></Alignment>
|
||||||
|
</Text>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
|
||||||
|
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
|
||||||
|
|
||||||
|
<xs:complexType name="AlignmentEnum" mixed="true">
|
||||||
|
<xs:complexContent>
|
||||||
|
<xs:extension base="t:enum">
|
||||||
|
<xs:choice>
|
||||||
|
<xs:element name="Right" type="xs:integer" fixed="0" minOccurs="0"/>
|
||||||
|
<xs:element name="Left" type="xs:integer" fixed="1" minOccurs="0"/>
|
||||||
|
<xs:element name="Center" type="xs:integer" fixed="2" minOccurs="0"/>
|
||||||
|
</xs:choice>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:complexContent>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:element name="Text">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>A visible font loaded from disk</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element name="Content" type="t:string" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>the content of the string printed</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Resource" type="t:string" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>The asset file, font resolution, example: Fonts/font.ttf,16</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Color" type="t:Color" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>Color</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Visible" type="t:bool" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>Wether the text is visible or not</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Alignment" type="AlignmentEnum" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>Text alignment</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
</xs:all>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||||
|
|
||||||
|
<Components>
|
||||||
|
<c:AABB/>
|
||||||
|
<c:Collidable/>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform/>
|
||||||
|
</Components>
|
||||||
|
|
||||||
|
<Children/>
|
||||||
|
|
||||||
|
</Entity>
|
||||||
@@ -6,14 +6,7 @@
|
|||||||
</Components>
|
</Components>
|
||||||
|
|
||||||
<Children>
|
<Children>
|
||||||
<Entity>
|
<Entity name="Ground">
|
||||||
<Components>
|
|
||||||
<c:Camera/>
|
|
||||||
<c:Transform/>
|
|
||||||
</Components>
|
|
||||||
<Children/>
|
|
||||||
</Entity>
|
|
||||||
<Entity>
|
|
||||||
<Components>
|
<Components>
|
||||||
<c:AABB/>
|
<c:AABB/>
|
||||||
<c:Collidable/>
|
<c:Collidable/>
|
||||||
@@ -22,46 +15,116 @@
|
|||||||
<Color A="1" B="0.513725519" G="0" R="1"/>
|
<Color A="1" B="0.513725519" G="0" R="1"/>
|
||||||
</c:Model>
|
</c:Model>
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="0" Y="2" Z="0"/>
|
<Position X="7" Y="-0.727000058" Z="-1.22800004"/>
|
||||||
<Scale X="5" Y="1" Z="5"/>
|
<Scale X="50" Y="1.45100009" Z="50"/>
|
||||||
</c:Transform>
|
</c:Transform>
|
||||||
</Components>
|
</Components>
|
||||||
<Children/>
|
<Children/>
|
||||||
</Entity>
|
</Entity>
|
||||||
<Entity name="Player">
|
<Entity name="Spawner">
|
||||||
<Components>
|
<Components>
|
||||||
<c:AABB>
|
<c:PlayerSpawn/>
|
||||||
<Origin X="0" Y="0.773000062" Z="0"/>
|
<c:Spawner>
|
||||||
<Size X="1" Y="1.60000002" Z="1"/>
|
<EntityFile>Schema/Entities/Player.xml</EntityFile>
|
||||||
</c:AABB>
|
</c:Spawner>
|
||||||
<c:Collidable/>
|
<c:Team>
|
||||||
<c:Physics/>
|
<Team>
|
||||||
<c:Model>
|
<Red/>
|
||||||
<Resource>Models/Assault.obj</Resource>
|
</Team>
|
||||||
<Color A="1" B="1" G="0" R="0"/>
|
</c:Team>
|
||||||
</c:Model>
|
|
||||||
<c:Player/>
|
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="0" Y="2.52699995" Z="0.0542778969"/>
|
<Position X="0.300000012" Y="0.0270000007" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:SpawnPoint/>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Assault.obj</Resource>
|
||||||
|
<Color A="1" B="0" G="0" R="1"/>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0.800000012" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:SpawnPoint/>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Assault.obj</Resource>
|
||||||
|
<Color A="1" B="0.0117647061" G="0" R="1"/>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="-0.600000024" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
<Entity name="DirectionalLight">
|
||||||
|
<Components>
|
||||||
|
<c:DirectionalLight/>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/DirectionalLightWidget.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="-6.00145912" Y="1.42697716" Z="3.04144025"/>
|
||||||
|
<Orientation X="5.69400024" Y="841.179565" Z="0"/>
|
||||||
</c:Transform>
|
</c:Transform>
|
||||||
</Components>
|
</Components>
|
||||||
<Children/>
|
<Children/>
|
||||||
</Entity>
|
</Entity>
|
||||||
<Entity>
|
<Entity name="ObstacleCourse">
|
||||||
|
<Components>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Test/ObstacleCourse.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform/>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity name="ObstacleCoursePlayerBox">
|
||||||
<Components>
|
<Components>
|
||||||
<c:AABB/>
|
<c:AABB/>
|
||||||
<c:Collidable/>
|
<c:Collidable/>
|
||||||
<c:Physics>
|
|
||||||
<Velocity X="0" Y="-0.0934068039" Z="0"/>
|
|
||||||
</c:Physics>
|
|
||||||
<c:Model>
|
<c:Model>
|
||||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||||
<Color A="1" B="0" G="1" R="1"/>
|
|
||||||
</c:Model>
|
</c:Model>
|
||||||
<c:Player/>
|
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="0" Y="4.15580511" Z="0"/>
|
<Position X="6.32800007" Y="0.807000041" Z="-2.2750001"/>
|
||||||
<Scale X="0.704558551" Y="0.115156889" Z="1"/>
|
<Scale X="1" Y="1.60000002" Z="1"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity name="ObstacleCourse1uHigh">
|
||||||
|
<Components>
|
||||||
|
<c:AABB/>
|
||||||
|
<c:Collidable/>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="9.11900043" Y="0.5" Z="-2.10900021"/>
|
||||||
|
<Scale X="1" Y="1" Z="8.1960001"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity name="ObstacleCourseWhoTheFuckKnows">
|
||||||
|
<Components>
|
||||||
|
<c:AABB/>
|
||||||
|
<c:Collidable/>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="13.2370005" Y="1.28600001" Z="-1.71700013"/>
|
||||||
|
<Scale X="2.58000016" Y="2.58300018" Z="21.1860008"/>
|
||||||
</c:Transform>
|
</c:Transform>
|
||||||
</Components>
|
</Components>
|
||||||
<Children/>
|
<Children/>
|
||||||
|
|||||||
@@ -2,17 +2,89 @@
|
|||||||
<Entity name="Player" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
<Entity name="Player" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||||
|
|
||||||
<Components>
|
<Components>
|
||||||
<c:AABB/>
|
<c:AABB>
|
||||||
<c:Physics/>
|
<Origin X="0" Y="0.772000015" Z="0"/>
|
||||||
|
<Size X="1" Y="1.60000002" Z="1"/>
|
||||||
|
</c:AABB>
|
||||||
<c:Collidable/>
|
<c:Collidable/>
|
||||||
<c:Model>
|
<c:Physics/>
|
||||||
<Resource>Models/Core/UnitSphere.obj</Resource>
|
<c:Player>
|
||||||
<Color A="1" B="1" G="0" R="0"/>
|
<MovementSpeed>3</MovementSpeed>
|
||||||
</c:Model>
|
</c:Player>
|
||||||
<c:Player/>
|
<c:Team>
|
||||||
<c:Transform/>
|
<Team>
|
||||||
|
<Red/>
|
||||||
|
</Team>
|
||||||
|
</c:Team>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0" Z="7.38143063"/>
|
||||||
|
</c:Transform>
|
||||||
</Components>
|
</Components>
|
||||||
|
|
||||||
<Children/>
|
<Children>
|
||||||
|
<Entity name="Camera">
|
||||||
|
<Components>
|
||||||
|
<c:Camera/>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="1.37700009" Z="0"/>
|
||||||
|
<Orientation X="6.28300047" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity name="PlayerName">
|
||||||
|
<Components>
|
||||||
|
<c:Text>
|
||||||
|
<Content></Content>
|
||||||
|
<Resource>Fonts/DroidSans.ttf,100</Resource>
|
||||||
|
<Color A="1" B="0" G="1" R="0"/>
|
||||||
|
</c:Text>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0.0263664704" Z="-0.447885782"/>
|
||||||
|
<Scale X="0.100000001" Y="0.113000005" Z="0.5"/>
|
||||||
|
<Orientation X="0" Y="3.14199996" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity name="CameraModel">
|
||||||
|
<Components>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Camera.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0.0331346765" Z="-0.0792061687"/>
|
||||||
|
<Scale X="1.30000007" Y="1.50000012" Z="1"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
<Entity name="ThirdPersonCamera">
|
||||||
|
<Components>
|
||||||
|
<c:Camera/>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Camera.obj</Resource>
|
||||||
|
<Visible>false</Visible>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="-0.284000009" Y="1.83800006" Z="1.18900001"/>
|
||||||
|
<Orientation X="5.95600033" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity name="PlayerModel">
|
||||||
|
<Components>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/AssaultHeadless.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Orientation X="0" Y="3.14159274" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
|
||||||
</Entity>
|
</Entity>
|
||||||
|
|||||||
@@ -1,58 +1,262 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
|
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||||
|
|
||||||
<Components>
|
<Components>
|
||||||
<c:Transform>
|
<c:Transform/>
|
||||||
<Position X="0" Y="0" Z="0"/>
|
</Components>
|
||||||
<Orientation X="0" Y="0" Z="0"/>
|
|
||||||
</c:Transform>
|
<Children>
|
||||||
</Components>
|
<Entity>
|
||||||
<Children>
|
<Components>
|
||||||
<Entity>
|
<c:Camera>
|
||||||
<Components>
|
<Name>ActionCamera</Name>
|
||||||
<c:Transform>
|
</c:Camera>
|
||||||
<Position X="0" Y="1" Z="10"/>
|
<c:Model>
|
||||||
</c:Transform>
|
<Resource>Models/Camera.obj</Resource>
|
||||||
<c:Model>
|
</c:Model>
|
||||||
<Resource>Models/Camera.obj</Resource>
|
<c:Transform>
|
||||||
</c:Model>
|
<Position X="-0.504807115" Y="6.00582743" Z="9.68687439"/>
|
||||||
<c:Camera>
|
<Orientation X="-0.733036518" Y="0.000105090476" Z="5.12391125e-07"/>
|
||||||
<Name>MainCamera</Name>
|
</c:Transform>
|
||||||
</c:Camera>
|
</Components>
|
||||||
</Components>
|
<Children>
|
||||||
</Entity>
|
<Entity>
|
||||||
<Entity>
|
<Components>
|
||||||
<Components>
|
<c:Text>
|
||||||
<c:Transform>
|
<Content>Camera #2</Content>
|
||||||
<Position X="5" Y="1" Z="5"/>
|
<Resource>Fonts/DroidSans.ttf,64</Resource>
|
||||||
</c:Transform>
|
<Alignment>0</Alignment>
|
||||||
<c:Model>
|
</c:Text>
|
||||||
<Resource>Models/Camera.obj</Resource>
|
<c:Transform>
|
||||||
</c:Model>
|
<Position X="0.700063765" Y="0.310270816" Z="-1"/>
|
||||||
<c:Camera>
|
<Scale X="0.100000001" Y="0.100000001" Z="0.100000001"/>
|
||||||
<Name>ActionCamera</Name>
|
</c:Transform>
|
||||||
</c:Camera>
|
</Components>
|
||||||
</Components>
|
<Children/>
|
||||||
</Entity>
|
</Entity>
|
||||||
<Entity>
|
</Children>
|
||||||
<Components>
|
</Entity>
|
||||||
<c:Transform>
|
<Entity>
|
||||||
<Position X="0" Y="-1" Z="0"/>
|
<Components>
|
||||||
<Scale X="100" Y="1" Z="100"/>
|
<c:Model>
|
||||||
</c:Transform>
|
<Resource>Models/Core/UnitPlane.obj</Resource>
|
||||||
<c:Model>
|
</c:Model>
|
||||||
<Resource>Models/Core/UnitPlane.obj</Resource>
|
<c:Transform>
|
||||||
</c:Model>
|
<Position X="0" Y="-1" Z="0.600000024"/>
|
||||||
</Components>
|
<Scale X="100" Y="1" Z="100"/>
|
||||||
</Entity>
|
</c:Transform>
|
||||||
<Entity>
|
</Components>
|
||||||
<Components>
|
<Children/>
|
||||||
<c:Transform>
|
</Entity>
|
||||||
<Position X="0" Y="0" Z="0"/>
|
<Entity>
|
||||||
</c:Transform>
|
<Components>
|
||||||
<c:Model>
|
<c:Model>
|
||||||
<Resource>An error</Resource>
|
<Resource>Models/Assault.obj</Resource>
|
||||||
</c:Model>
|
</c:Model>
|
||||||
</Components>
|
<c:Transform>
|
||||||
</Entity>
|
<Position X="-2.5" Y="0" Z="1"/>
|
||||||
</Children>
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:Text>
|
||||||
|
<Content>Welcome!</Content>
|
||||||
|
<Resource>Fonts/DroidSans.ttf,1280</Resource>
|
||||||
|
</c:Text>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0" Z="0.700000048"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:RaptorCopter>
|
||||||
|
<Speed>2</Speed>
|
||||||
|
<Axis X="0" Y="1" Z="0"/>
|
||||||
|
</c:RaptorCopter>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="2.37320328" Z="0"/>
|
||||||
|
<Orientation X="0" Y="8252.15918" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:PointLight>
|
||||||
|
<Color A="1" B="1" G="0" R="1"/>
|
||||||
|
<Radius>6</Radius>
|
||||||
|
<Intensity>0.5</Intensity>
|
||||||
|
</c:PointLight>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="-2.5" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:PointLight>
|
||||||
|
<Color A="1" B="0" G="0" R="1"/>
|
||||||
|
<Radius>8</Radius>
|
||||||
|
</c:PointLight>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="-5" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:PointLight>
|
||||||
|
<Color A="1" B="0" G="1" R="1"/>
|
||||||
|
<Radius>6</Radius>
|
||||||
|
<Intensity>0.5</Intensity>
|
||||||
|
</c:PointLight>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0" Z="-2.5"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:PointLight>
|
||||||
|
<Color A="1" B="0" G="1" R="0"/>
|
||||||
|
<Radius>8</Radius>
|
||||||
|
</c:PointLight>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0" Z="-5"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:PointLight>
|
||||||
|
<Color A="1" B="1" G="1" R="0"/>
|
||||||
|
<Radius>6</Radius>
|
||||||
|
<Intensity>0.5</Intensity>
|
||||||
|
</c:PointLight>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0" Z="2.5"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:PointLight>
|
||||||
|
<Color A="1" B="1" G="0.00784313772" R="0"/>
|
||||||
|
<Radius>8</Radius>
|
||||||
|
</c:PointLight>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0" Z="5"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:PointLight>
|
||||||
|
<Radius>6</Radius>
|
||||||
|
<Intensity>0.5</Intensity>
|
||||||
|
</c:PointLight>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="2.5" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:PointLight>
|
||||||
|
<Radius>8</Radius>
|
||||||
|
</c:PointLight>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="5" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Assault.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="2.5" Y="0" Z="1"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:Camera>
|
||||||
|
<Name>MainCamera</Name>
|
||||||
|
</c:Camera>
|
||||||
|
<c:Listener/>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Camera.obj</Resource>
|
||||||
|
<Visible>false</Visible>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="-1.27354908" Y="5.18422079" Z="10.6223917"/>
|
||||||
|
<Orientation X="-0.436328411" Y="-0.0523675606" Z="1.67869363e-08"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:Text>
|
||||||
|
<Content>Taiwan #1</Content>
|
||||||
|
<Resource>Fonts/DroidSans.ttf,64</Resource>
|
||||||
|
<Alignment>0</Alignment>
|
||||||
|
</c:Text>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="0.716896772" Y="0.296712071" Z="-1"/>
|
||||||
|
<Scale X="0.100000001" Y="0.100000001" Z="0.100000001"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:DirectionalLight>
|
||||||
|
<Color A="1" B="0.996078432" G="1" R="1"/>
|
||||||
|
<Intensity>0.80000001192092896</Intensity>
|
||||||
|
</c:DirectionalLight>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/DirectionalLightWidget.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="-0.0013256073" Y="1.89540339" Z="6.53467274"/>
|
||||||
|
<Orientation X="-0.859663308" Y="-0.100310192" Z="-0.404723018"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||||
|
</c:Model>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="-5.4082036" Y="0" Z="-1.84950542"/>
|
||||||
|
</c:Transform>
|
||||||
|
</Components>
|
||||||
|
<Children/>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
|
|
||||||
</Entity>
|
</Entity>
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
<xs:simpleType name="double">
|
<xs:simpleType name="double">
|
||||||
<xs:restriction base="xs:decimal"></xs:restriction>
|
<xs:restriction base="xs:decimal"></xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
<xs:simpleType name="float">
|
||||||
|
<xs:restriction base="xs:decimal"></xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
<xs:simpleType name="string">
|
<xs:simpleType name="string">
|
||||||
<xs:restriction base="xs:string"></xs:restriction>
|
<xs:restriction base="xs:string"></xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
|
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
|
||||||
<xs:element ref="c:Player" minOccurs="0"/>
|
<xs:element ref="c:Player" minOccurs="0"/>
|
||||||
<xs:element ref="c:Camera" minOccurs="0"/>
|
<xs:element ref="c:Camera" minOccurs="0"/>
|
||||||
|
<xs:element ref="c:Text" minOccurs="0"/>
|
||||||
<xs:element ref="c:AABB" minOccurs="0"/>
|
<xs:element ref="c:AABB" minOccurs="0"/>
|
||||||
<xs:element ref="c:Trigger" minOccurs="0"/>
|
<xs:element ref="c:Trigger" minOccurs="0"/>
|
||||||
<xs:element ref="c:Health" minOccurs="0"/>
|
<xs:element ref="c:Health" minOccurs="0"/>
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#version 430
|
||||||
|
in vec2 TexCoords;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
uniform sampler2D text;
|
||||||
|
uniform vec3 textColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
|
||||||
|
color = vec4(textColor, 1.0) * sampled;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#version 430
|
||||||
|
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
|
||||||
|
out vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform mat4 M;
|
||||||
|
uniform mat4 V;
|
||||||
|
uniform mat4 P;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = P * V * M * vec4(vertex.xy, 0.0, 1.0);
|
||||||
|
TexCoords = vertex.zw;
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ find_package(assimp REQUIRED)
|
|||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
find_package(PNG REQUIRED)
|
find_package(PNG REQUIRED)
|
||||||
find_package(Xerces REQUIRED)
|
find_package(Xerces REQUIRED)
|
||||||
|
find_package(Freetype REQUIRED)
|
||||||
# Because FindOpenAL is retarded
|
# Because FindOpenAL is retarded
|
||||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_SOURCE_DIR}/deps/include/OpenAL")
|
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_SOURCE_DIR}/deps/include/OpenAL")
|
||||||
find_package(OpenAL REQUIRED)
|
find_package(OpenAL REQUIRED)
|
||||||
@@ -25,6 +26,7 @@ include_directories(
|
|||||||
${assimp_INCLUDE_DIRS}
|
${assimp_INCLUDE_DIRS}
|
||||||
${PNG_INCLUDE_DIRS}
|
${PNG_INCLUDE_DIRS}
|
||||||
${Xerces_INCLUDE_DIRS}
|
${Xerces_INCLUDE_DIRS}
|
||||||
|
${FREETYPE_INCLUDE_DIRS}
|
||||||
${OPENAL_INCLUDE_DIR}
|
${OPENAL_INCLUDE_DIR}
|
||||||
${X11_INCLUDE_DIRS}
|
${X11_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
@@ -126,6 +128,7 @@ set(LIBRARIES
|
|||||||
${assimp_LIBRARIES}
|
${assimp_LIBRARIES}
|
||||||
${PNG_LIBRARIES}
|
${PNG_LIBRARIES}
|
||||||
${Xerces_LIBRARIES}
|
${Xerces_LIBRARIES}
|
||||||
|
${FREETYPE_LIBRARIES}
|
||||||
${OPENAL_LIBRARY}
|
${OPENAL_LIBRARY}
|
||||||
${X11_LIBRARIES}
|
${X11_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Inv
|
|||||||
|
|
||||||
bool EntityWrapper::HasComponent(const std::string& componentName)
|
bool EntityWrapper::HasComponent(const std::string& componentName)
|
||||||
{
|
{
|
||||||
|
if (!Valid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return World->HasComponent(ID, componentName);
|
return World->HasComponent(ID, componentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,6 +20,34 @@ EntityWrapper EntityWrapper::Parent()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityWrapper EntityWrapper::FirstChildByName(const std::string& name)
|
||||||
|
{
|
||||||
|
auto itPair = this->World->GetChildren(this->ID);
|
||||||
|
if (itPair.first == itPair.second) {
|
||||||
|
return EntityWrapper::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = itPair.first; it != itPair.second; ++it) {
|
||||||
|
if (this->World->GetName(it->second) == name) {
|
||||||
|
return EntityWrapper(this->World, it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EntityWrapper::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityWrapper::IsChildOf(EntityWrapper potentialParent)
|
||||||
|
{
|
||||||
|
EntityWrapper entity = *this;
|
||||||
|
while (entity.Parent().Valid()) {
|
||||||
|
entity = entity.Parent();
|
||||||
|
if (entity == potentialParent) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool EntityWrapper::Valid()
|
bool EntityWrapper::Valid()
|
||||||
{
|
{
|
||||||
if (this->World == nullptr) {
|
if (this->World == nullptr) {
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ std::vector<int> Child::childIndicesContainingBox(const AABB& box) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Child::hasChildren() const
|
bool Child::hasChildren() const
|
||||||
{
|
{
|
||||||
return m_Children[0] != nullptr;
|
return m_Children[0] != nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
#include "Core/Transform.h"
|
#include "Core/Transform.h"
|
||||||
|
|
||||||
|
glm::vec3 Transform::AbsolutePosition(EntityWrapper entity)
|
||||||
|
{
|
||||||
|
return AbsolutePosition(entity.World, entity.ID);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity)
|
glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity)
|
||||||
{
|
{
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
@@ -14,6 +19,11 @@ glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity)
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::quat Transform::AbsoluteOrientation(EntityWrapper entity)
|
||||||
|
{
|
||||||
|
return AbsoluteOrientation(entity.World, entity.ID);
|
||||||
|
}
|
||||||
|
|
||||||
glm::quat Transform::AbsoluteOrientation(World* world, EntityID entity)
|
glm::quat Transform::AbsoluteOrientation(World* world, EntityID entity)
|
||||||
{
|
{
|
||||||
glm::quat orientation;
|
glm::quat orientation;
|
||||||
@@ -27,6 +37,11 @@ glm::quat Transform::AbsoluteOrientation(World* world, EntityID entity)
|
|||||||
return orientation;
|
return orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 Transform::AbsoluteScale(EntityWrapper entity)
|
||||||
|
{
|
||||||
|
return AbsoluteScale(entity.World, entity.ID);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 Transform::AbsoluteScale(World* world, EntityID entity)
|
glm::vec3 Transform::AbsoluteScale(World* world, EntityID entity)
|
||||||
{
|
{
|
||||||
glm::vec3 scale(1.f);
|
glm::vec3 scale(1.f);
|
||||||
@@ -40,6 +55,11 @@ glm::vec3 Transform::AbsoluteScale(World* world, EntityID entity)
|
|||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::mat4 Transform::ModelMatrix(EntityWrapper entity)
|
||||||
|
{
|
||||||
|
return ModelMatrix(entity.ID, entity.World);
|
||||||
|
}
|
||||||
|
|
||||||
glm::mat4 Transform::ModelMatrix(EntityID entity, World* world)
|
glm::mat4 Transform::ModelMatrix(EntityID entity, World* world)
|
||||||
{
|
{
|
||||||
glm::vec3 position = Transform::AbsolutePosition(world, entity);
|
glm::vec3 position = Transform::AbsolutePosition(world, entity);
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re
|
|||||||
m_EditorWorldSystemPipeline->AddSystem<EditorWidgetSystem>(0, m_Renderer);
|
m_EditorWorldSystemPipeline->AddSystem<EditorWidgetSystem>(0, m_Renderer);
|
||||||
m_EditorWorldSystemPipeline->AddSystem<EditorRenderSystem>(1, m_Renderer, m_RenderFrame);
|
m_EditorWorldSystemPipeline->AddSystem<EditorRenderSystem>(1, m_Renderer, m_RenderFrame);
|
||||||
|
|
||||||
m_Camera = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/Empty.xml");
|
m_EditorCamera = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/Empty.xml");
|
||||||
m_EditorWorld->AttachComponent(m_Camera.ID, "Transform");
|
m_ActualCamera = m_EditorCamera;
|
||||||
m_EditorWorld->AttachComponent(m_Camera.ID, "Camera");
|
m_EditorWorld->AttachComponent(m_EditorCamera.ID, "Transform");
|
||||||
m_DebugCameraInputController = new DebugCameraInputController<EditorSystem>(m_EventBroker, -1);
|
m_EditorWorld->AttachComponent(m_EditorCamera.ID, "Camera");
|
||||||
|
m_EditorCameraInputController = new EditorCameraInputController<EditorSystem>(m_EventBroker, -1);
|
||||||
|
|
||||||
m_EditorGUI = new EditorGUI(m_World, m_EventBroker);
|
m_EditorGUI = new EditorGUI(m_World, m_EventBroker);
|
||||||
m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1));
|
m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1));
|
||||||
@@ -33,38 +34,70 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re
|
|||||||
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta);
|
EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &EditorSystem::OnSetCamera);
|
||||||
|
|
||||||
m_EditorStats = new EditorStats();
|
m_EditorStats = new EditorStats();
|
||||||
|
|
||||||
Events::SetCamera e;
|
if (m_Enabled) {
|
||||||
e.CameraEntity = m_Camera;
|
Enable();
|
||||||
m_EventBroker->Publish(e);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorSystem::~EditorSystem()
|
EditorSystem::~EditorSystem()
|
||||||
{
|
{
|
||||||
delete m_EditorStats;
|
delete m_EditorStats;
|
||||||
delete m_EditorGUI;
|
delete m_EditorGUI;
|
||||||
delete m_DebugCameraInputController;
|
delete m_EditorCameraInputController;
|
||||||
delete m_EditorWorldSystemPipeline;
|
delete m_EditorWorldSystemPipeline;
|
||||||
delete m_EditorWorld;
|
delete m_EditorWorld;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorSystem::Update(double dt)
|
void EditorSystem::Update(double dt)
|
||||||
{
|
{
|
||||||
m_EventBroker->Process<EditorGUI>();
|
double now = glfwGetTime();
|
||||||
m_EditorGUI->Draw();
|
double actualDelta = now - m_LastTime;
|
||||||
m_EditorStats->Draw(dt);
|
m_LastTime = now;
|
||||||
|
|
||||||
if (m_CurrentSelection.Valid() && m_Widget.Valid()) {
|
if (m_Enabled) {
|
||||||
(glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID);
|
m_EventBroker->Process<EditorGUI>();
|
||||||
|
m_EditorGUI->Draw();
|
||||||
|
m_EditorStats->Draw(actualDelta);
|
||||||
|
|
||||||
|
if (m_CurrentSelection.Valid() && m_Widget.Valid()) {
|
||||||
|
(glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_EditorWorldSystemPipeline->Update(actualDelta);
|
||||||
|
|
||||||
|
ComponentWrapper& cameraTransform = m_EditorCamera["Transform"];
|
||||||
|
glm::vec3& ori = cameraTransform["Orientation"];
|
||||||
|
ori.x = m_EditorCameraInputController->Rotation().x;
|
||||||
|
ori.y = m_EditorCameraInputController->Rotation().y;
|
||||||
|
glm::vec3& pos = cameraTransform["Position"];
|
||||||
|
pos += m_EditorCameraInputController->Movement() * glm::inverse(glm::quat(ori)) * (float)actualDelta;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_EditorWorldSystemPipeline->Update(dt);
|
void EditorSystem::Enable()
|
||||||
|
{
|
||||||
|
m_EditorCameraInputController->Enable();
|
||||||
|
m_EventBroker->Publish(Events::UnlockMouse());
|
||||||
|
Events::SetCamera e;
|
||||||
|
e.CameraEntity = m_EditorCamera;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
(glm::vec3&)m_EditorCamera["Transform"]["Position"] = Transform::AbsolutePosition(m_ActualCamera);
|
||||||
|
m_Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
m_DebugCameraInputController->Update(dt);
|
void EditorSystem::Disable()
|
||||||
m_Camera["Transform"]["Position"] = m_DebugCameraInputController->Position();
|
{
|
||||||
m_Camera["Transform"]["Orientation"] = glm::eulerAngles(m_DebugCameraInputController->Orientation());
|
m_EditorCameraInputController->Disable();
|
||||||
|
m_EventBroker->Publish(Events::LockMouse());
|
||||||
|
Events::SetCamera e;
|
||||||
|
e.CameraEntity = m_ActualCamera;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
m_Enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorSystem::OnEntitySelected(EntityWrapper entity)
|
void EditorSystem::OnEntitySelected(EntityWrapper entity)
|
||||||
@@ -148,6 +181,33 @@ bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EditorSystem::OnInputCommand(const Events::InputCommand& e)
|
||||||
|
{
|
||||||
|
if (e.PlayerID != -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Command == "ToggleEditor" && e.Value > 0) {
|
||||||
|
if (m_Enabled) {
|
||||||
|
Disable();
|
||||||
|
} else {
|
||||||
|
Enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EditorSystem::OnSetCamera(const Events::SetCamera& e)
|
||||||
|
{
|
||||||
|
if (m_Enabled && e.CameraEntity != m_EditorCamera) {
|
||||||
|
m_ActualCamera = e.CameraEntity;
|
||||||
|
Events::SetCamera e2;
|
||||||
|
e2.CameraEntity = m_EditorCamera;
|
||||||
|
m_EventBroker->Publish(e2);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem::path filePath)
|
EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem::path filePath)
|
||||||
{
|
{
|
||||||
if (parent.World == nullptr) {
|
if (parent.World == nullptr) {
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#include "Input/FirstPersonInputController.h"
|
||||||
|
|
||||||
@@ -5,14 +5,20 @@ using namespace boost::asio::ip;
|
|||||||
|
|
||||||
Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
||||||
{
|
{
|
||||||
|
Network::initialize();
|
||||||
|
|
||||||
// Asumes root node is EntityID 0
|
// Asumes root node is EntityID 0
|
||||||
insertIntoServerClientMaps(0, 0);
|
insertIntoServerClientMaps(0, 0);
|
||||||
|
// Init timer
|
||||||
|
m_TimeSinceSentInputs = std::clock();
|
||||||
// Default is local host
|
// Default is local host
|
||||||
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
||||||
int port = config->Get<int>("Networking.Port", 13);
|
int port = config->Get<int>("Networking.Port", 13);
|
||||||
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
|
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
|
||||||
// Set up network stream
|
// Set up network stream
|
||||||
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
|
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
|
||||||
|
m_SendInputIntervalMs = config->Get<int>("Networking.SendInputIntervalMs", 33);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
@@ -37,19 +43,24 @@ void Client::Update()
|
|||||||
readFromServer();
|
readFromServer();
|
||||||
if (m_IsConnected) {
|
if (m_IsConnected) {
|
||||||
hasServerTimedOut();
|
hasServerTimedOut();
|
||||||
|
// Don't sent 1 input in 1 packet, bunch em up.
|
||||||
|
if (m_SendInputIntervalMs < (1000 * (std::clock() - m_TimeSinceSentInputs) / (double)CLOCKS_PER_SEC)) {
|
||||||
|
sendInputCommands();
|
||||||
|
m_TimeSinceSentInputs = std::clock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Network::Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::readFromServer()
|
void Client::readFromServer()
|
||||||
{
|
{
|
||||||
while (m_Socket.available()) {
|
while (m_Socket.available()) {
|
||||||
bytesRead = receive(readBuf, INPUTSIZE);
|
bytesRead = receive(readBuf);
|
||||||
if (bytesRead > 0) {
|
if (bytesRead > 0) {
|
||||||
Packet packet(readBuf, bytesRead);
|
Packet packet(readBuf, bytesRead);
|
||||||
parseMessageType(packet);
|
parseMessageType(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendInputCommands();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::parseMessageType(Packet& packet)
|
void Client::parseMessageType(Packet& packet)
|
||||||
@@ -66,12 +77,9 @@ void Client::parseMessageType(Packet& packet)
|
|||||||
case MessageType::Connect:
|
case MessageType::Connect:
|
||||||
parseConnect(packet);
|
parseConnect(packet);
|
||||||
break;
|
break;
|
||||||
case MessageType::ClientPing:
|
case MessageType::Ping:
|
||||||
parsePing();
|
parsePing();
|
||||||
break;
|
break;
|
||||||
case MessageType::ServerPing:
|
|
||||||
parseServerPing();
|
|
||||||
break;
|
|
||||||
case MessageType::Message:
|
case MessageType::Message:
|
||||||
break;
|
break;
|
||||||
case MessageType::Snapshot:
|
case MessageType::Snapshot:
|
||||||
@@ -81,6 +89,13 @@ void Client::parseMessageType(Packet& packet)
|
|||||||
break;
|
break;
|
||||||
case MessageType::PlayerConnected:
|
case MessageType::PlayerConnected:
|
||||||
parsePlayerConnected(packet);
|
parsePlayerConnected(packet);
|
||||||
|
break;
|
||||||
|
case MessageType::Kick:
|
||||||
|
parseKick();
|
||||||
|
break;
|
||||||
|
case MessageType::OnPlayerSpawned:
|
||||||
|
parsePlayersSpawned(packet);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -99,11 +114,6 @@ void Client::parsePlayerConnected(Packet & packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::parsePing()
|
void Client::parsePing()
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::parseServerPing()
|
|
||||||
{
|
{
|
||||||
// Might miss connect message so set it here instead.
|
// Might miss connect message so set it here instead.
|
||||||
m_IsConnected = true;
|
m_IsConnected = true;
|
||||||
@@ -112,11 +122,26 @@ void Client::parseServerPing()
|
|||||||
LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime);
|
LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime);
|
||||||
m_StartPingTime = std::clock();
|
m_StartPingTime = std::clock();
|
||||||
|
|
||||||
Packet packet(MessageType::ServerPing, m_SendPacketID);
|
Packet packet(MessageType::Ping, m_SendPacketID);
|
||||||
packet.WriteString("Ping recieved");
|
packet.WriteString("Ping recieved");
|
||||||
send(packet);
|
send(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::parseKick()
|
||||||
|
{
|
||||||
|
LOG_WARNING("You have been kicked from the server.");
|
||||||
|
m_IsConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::parsePlayersSpawned(Packet& packet)
|
||||||
|
{
|
||||||
|
Events::PlayerSpawned e;
|
||||||
|
e.Player = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive<EntityID>()]);
|
||||||
|
e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive<EntityID>()]);
|
||||||
|
e.PlayerID = -1;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
}
|
||||||
|
|
||||||
// Fields with strings will not work right now
|
// Fields with strings will not work right now
|
||||||
void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
|
void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
|
||||||
{
|
{
|
||||||
@@ -153,8 +178,12 @@ void Client::parseSnapshot(Packet& packet)
|
|||||||
{
|
{
|
||||||
std::string componentType = packet.ReadString();
|
std::string componentType = packet.ReadString();
|
||||||
while (packet.DataReadSize() < packet.Size()) {
|
while (packet.DataReadSize() < packet.Size()) {
|
||||||
|
// HACK
|
||||||
|
std::string entityName = packet.ReadString();
|
||||||
// Components EntityID
|
// Components EntityID
|
||||||
EntityID receivedEntityID = packet.ReadPrimitive<EntityID>();
|
EntityID receivedEntityID = packet.ReadPrimitive<EntityID>();
|
||||||
|
// HACK
|
||||||
|
m_World->SetName(receivedEntityID, entityName);
|
||||||
// Parents EntityID
|
// Parents EntityID
|
||||||
EntityID receivedParentEntityID = packet.ReadPrimitive<EntityID>();
|
EntityID receivedParentEntityID = packet.ReadPrimitive<EntityID>();
|
||||||
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
||||||
@@ -211,15 +240,20 @@ void Client::parseSnapshot(Packet& packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Client::receive(char* data, size_t length)
|
int Client::receive(char* data)
|
||||||
{
|
{
|
||||||
boost::system::error_code error;
|
boost::system::error_code error;
|
||||||
|
|
||||||
int bytesReceived = m_Socket.receive_from(boost
|
int bytesReceived = m_Socket.receive_from(boost
|
||||||
::asio::buffer((void*)data, length),
|
::asio::buffer((void*)data, INPUTSIZE),
|
||||||
m_ReceiverEndpoint,
|
m_ReceiverEndpoint,
|
||||||
0, error);
|
0, error);
|
||||||
|
// Network Debug data
|
||||||
|
if (isReadingData) {
|
||||||
|
m_NetworkData.TotalDataReceived += bytesReceived;
|
||||||
|
m_NetworkData.DataReceivedThisInterval += bytesReceived;
|
||||||
|
m_NetworkData.AmountOfMessagesReceived++;
|
||||||
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
//LOG_ERROR("receive: %s", error.message().c_str());
|
//LOG_ERROR("receive: %s", error.message().c_str());
|
||||||
}
|
}
|
||||||
@@ -232,6 +266,12 @@ void Client::send(Packet& packet)
|
|||||||
packet.Data(),
|
packet.Data(),
|
||||||
packet.Size()),
|
packet.Size()),
|
||||||
m_ReceiverEndpoint, 0);
|
m_ReceiverEndpoint, 0);
|
||||||
|
// Network Debug data
|
||||||
|
if (isReadingData) {
|
||||||
|
m_NetworkData.TotalDataSent += packet.Size();
|
||||||
|
m_NetworkData.DataSentThisInterval += packet.Size();
|
||||||
|
m_NetworkData.AmountOfMessagesSent++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::connect()
|
void Client::connect()
|
||||||
@@ -250,14 +290,6 @@ void Client::disconnect()
|
|||||||
send(packet);
|
send(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ping()
|
|
||||||
{
|
|
||||||
//Packet packet(MessageType::Connect, m_SendPacketID);
|
|
||||||
//packet.WriteString("Ping");
|
|
||||||
//m_StartPingTime = std::clock();
|
|
||||||
//send(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Client::OnInputCommand(const Events::InputCommand & e)
|
bool Client::OnInputCommand(const Events::InputCommand & e)
|
||||||
{
|
{
|
||||||
if (e.Command == "ConnectToServer") { // Connect for now
|
if (e.Command == "ConnectToServer") { // Connect for now
|
||||||
@@ -275,6 +307,15 @@ bool Client::OnInputCommand(const Events::InputCommand & e)
|
|||||||
if (e.Value > 0) {
|
if (e.Value > 0) {
|
||||||
becomePlayer();
|
becomePlayer();
|
||||||
}
|
}
|
||||||
|
} else if (e.Command == "LogNetworkBandwidth") {
|
||||||
|
if (e.Value > 0) {
|
||||||
|
// Save to file if we no longer want to read data.
|
||||||
|
if (isReadingData) {
|
||||||
|
saveToFile();
|
||||||
|
}
|
||||||
|
isReadingData = !isReadingData;
|
||||||
|
m_SaveDataTimer = std::clock();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
m_InputCommandBuffer.push_back(e);
|
m_InputCommandBuffer.push_back(e);
|
||||||
//LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
//LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||||
@@ -305,7 +346,7 @@ bool Client::hasServerTimedOut()
|
|||||||
{
|
{
|
||||||
// Time in ms
|
// Time in ms
|
||||||
float timeSincePing = 1000 * (std::clock() - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
|
float timeSincePing = 1000 * (std::clock() - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
|
||||||
if (timeSincePing > TIMEOUTMS) {
|
if (timeSincePing > m_TimeoutMs) {
|
||||||
// Clear everything and go to menu.
|
// Clear everything and go to menu.
|
||||||
LOG_INFO("Server has timed out, returning to menu, Beep Boop.");
|
LOG_INFO("Server has timed out, returning to menu, Beep Boop.");
|
||||||
m_IsConnected = false;
|
m_IsConnected = false;
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
#include "Network/Network.h"
|
||||||
|
|
||||||
|
void Network::Update()
|
||||||
|
{
|
||||||
|
updateNetworkData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::saveToFile()
|
||||||
|
{
|
||||||
|
std::ofstream outfile;
|
||||||
|
time_t t = time(0);
|
||||||
|
// get time now
|
||||||
|
struct tm * now = localtime(&t);
|
||||||
|
// Get current time and date
|
||||||
|
std::string dateAndTime = "BandwidthData - " + std::to_string(now->tm_year + 1900) + '-'
|
||||||
|
+ std::to_string(now->tm_mon + 1) + '-'
|
||||||
|
+ std::to_string(now->tm_mday) + '_'
|
||||||
|
+ std::to_string(now->tm_hour) + "h."
|
||||||
|
+ std::to_string(now->tm_min) + "m."
|
||||||
|
+ std::to_string(now->tm_sec) + 's';
|
||||||
|
|
||||||
|
outfile.open(dateAndTime + ".csv");
|
||||||
|
outfile << "Total time," + std::to_string(m_NetworkData.TotalTime) + "\n";
|
||||||
|
outfile << "Total data received," + std::to_string(m_NetworkData.TotalDataReceived) + "\n";
|
||||||
|
outfile << "Total data sent," + std::to_string(m_NetworkData.TotalDataSent) + "\n";
|
||||||
|
outfile << "Total messages received," + std::to_string(m_NetworkData.AmountOfMessagesReceived) + "\n";
|
||||||
|
outfile << "Total messages sent," + std::to_string(m_NetworkData.AmountOfMessagesSent) + "\n";
|
||||||
|
|
||||||
|
float messagesReceivedPerSec = (float)m_NetworkData.AmountOfMessagesReceived / (m_NetworkData.TotalTime / 1000);
|
||||||
|
float messagesSentPerSec = (float)m_NetworkData.AmountOfMessagesSent / (m_NetworkData.TotalTime / 1000);
|
||||||
|
float dataReceivedPerSec = (float)m_NetworkData.TotalDataReceived / (m_NetworkData.TotalTime / 1000);
|
||||||
|
float dataSentPerSec = (float)m_NetworkData.TotalDataSent / (m_NetworkData.TotalTime / 1000);
|
||||||
|
outfile << "Avarage messages received / s: " + std::to_string(messagesReceivedPerSec) + "\n";
|
||||||
|
outfile << "Avarage messages sents / s: " + std::to_string(messagesSentPerSec) + "\n";
|
||||||
|
outfile << "Avarage data received B/s: " + std::to_string(dataReceivedPerSec) + "\n";
|
||||||
|
outfile << "Avarage data sents B/s: " + std::to_string(dataSentPerSec) + "\n";
|
||||||
|
|
||||||
|
outfile << "time, avg receive B, avg send B\n";
|
||||||
|
for (int i = 0; i < m_NetworkData.BandwidthBytes.size(); i++) {
|
||||||
|
outfile << std::to_string(i) + ",";
|
||||||
|
outfile << std::to_string(m_NetworkData.BandwidthBytes[i].first) + ",";
|
||||||
|
outfile << std::to_string(m_NetworkData.BandwidthBytes[i].second) + "\n";
|
||||||
|
}
|
||||||
|
outfile.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::updateNetworkData()
|
||||||
|
{
|
||||||
|
std::clock_t currentTime = std::clock();
|
||||||
|
// Send snapshot
|
||||||
|
if (m_SaveDataIntervalMs < (1000 * (currentTime - m_SaveDataTimer) / (double)CLOCKS_PER_SEC)) {
|
||||||
|
// Set values
|
||||||
|
m_NetworkData.TotalTime += (1000 * (currentTime - m_SaveDataTimer) / (double)CLOCKS_PER_SEC);
|
||||||
|
m_NetworkData.BandwidthBytes.push_back(std::pair<unsigned int, unsigned int>(m_NetworkData.DataReceivedThisInterval, m_NetworkData.DataSentThisInterval));
|
||||||
|
// Reset interval stuff
|
||||||
|
m_SaveDataTimer = std::clock();
|
||||||
|
m_NetworkData.DataSentThisInterval = 0;
|
||||||
|
m_NetworkData.DataReceivedThisInterval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::initialize()
|
||||||
|
{
|
||||||
|
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||||
|
m_MaxConnections = config->Get<int>("Networking.MaxConnections", 8);
|
||||||
|
m_TimeoutMs = config->Get<int>("Networking.TimeoutMs", 20000);
|
||||||
|
}
|
||||||
@@ -39,6 +39,7 @@ void Packet::Init(MessageType type, unsigned int & packetID)
|
|||||||
Packet::WritePrimitive<int>(messageType);
|
Packet::WritePrimitive<int>(messageType);
|
||||||
Packet::WritePrimitive<int>(packetID);
|
Packet::WritePrimitive<int>(packetID);
|
||||||
packetID++;
|
packetID++;
|
||||||
|
m_HeaderSize = m_Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packet::WriteString(const std::string& str)
|
void Packet::WriteString(const std::string& str)
|
||||||
|
|||||||
+114
-39
@@ -1,7 +1,13 @@
|
|||||||
#include "Network/Server.h"
|
#include "Network/Server.h"
|
||||||
|
|
||||||
Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 13))
|
Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 27666))
|
||||||
{ }
|
{
|
||||||
|
Network::initialize();
|
||||||
|
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||||
|
snapshotInterval = 1000 * config->Get<float>("Networking.SnapshotInterval", 0.05);
|
||||||
|
pingIntervalMs = config->Get<float>("Networking.PingIntervalMs", 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
{
|
{
|
||||||
@@ -14,7 +20,8 @@ void Server::Start(World* world, EventBroker* eventBroker)
|
|||||||
m_EventBroker = eventBroker;
|
m_EventBroker = eventBroker;
|
||||||
// Subscribe to events
|
// Subscribe to events
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
|
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
|
||||||
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
|
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned);
|
||||||
|
for (size_t i = 0; i < m_MaxConnections; i++) {
|
||||||
m_PlayerDefinitions[i].StopTime = std::clock();
|
m_PlayerDefinitions[i].StopTime = std::clock();
|
||||||
}
|
}
|
||||||
LOG_INFO("I am Server. BIP BOP\n");
|
LOG_INFO("I am Server. BIP BOP\n");
|
||||||
@@ -24,14 +31,17 @@ void Server::Update()
|
|||||||
{
|
{
|
||||||
readFromClients();
|
readFromClients();
|
||||||
m_EventBroker->Process<Server>();
|
m_EventBroker->Process<Server>();
|
||||||
}
|
if (isReadingData) {
|
||||||
|
Network::Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Server::readFromClients()
|
void Server::readFromClients()
|
||||||
{
|
{
|
||||||
while (m_Socket.available()) {
|
while (m_Socket.available()) {
|
||||||
try {
|
try {
|
||||||
bytesRead = receive(readBuffer, INPUTSIZE);
|
bytesRead = receive(readBuffer);
|
||||||
Packet packet(readBuffer, bytesRead);
|
Packet packet(readBuffer, bytesRead);
|
||||||
parseMessageType(packet);
|
parseMessageType(packet);
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
@@ -46,7 +56,7 @@ void Server::readFromClients()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send pings each
|
// Send pings each
|
||||||
if (intervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) {
|
if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) {
|
||||||
sendPing();
|
sendPing();
|
||||||
previousePingMessage = currentTime;
|
previousePingMessage = currentTime;
|
||||||
}
|
}
|
||||||
@@ -70,11 +80,8 @@ void Server::parseMessageType(Packet& packet)
|
|||||||
case MessageType::Connect:
|
case MessageType::Connect:
|
||||||
parseConnect(packet);
|
parseConnect(packet);
|
||||||
break;
|
break;
|
||||||
case MessageType::ClientPing:
|
case MessageType::Ping:
|
||||||
//parseClientPing();
|
parsePing();
|
||||||
break;
|
|
||||||
case MessageType::ServerPing:
|
|
||||||
parseServerPing();
|
|
||||||
break;
|
break;
|
||||||
case MessageType::Message:
|
case MessageType::Message:
|
||||||
break;
|
break;
|
||||||
@@ -97,21 +104,47 @@ void Server::parseMessageType(Packet& packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Server::receive(char * data, size_t length)
|
int Server::receive(char * data)
|
||||||
{
|
{
|
||||||
length = m_Socket.receive_from(
|
unsigned int length = m_Socket.receive_from(
|
||||||
boost::asio::buffer((void*)data
|
boost::asio::buffer((void*)data
|
||||||
, length)
|
, INPUTSIZE)
|
||||||
, m_ReceiverEndpoint, 0);
|
, m_ReceiverEndpoint, 0);
|
||||||
|
// Network Debug data
|
||||||
|
if (isReadingData) {
|
||||||
|
m_NetworkData.TotalDataReceived += length;
|
||||||
|
m_NetworkData.DataReceivedThisInterval += length;
|
||||||
|
m_NetworkData.AmountOfMessagesReceived++;
|
||||||
|
}
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::send(Packet& packet, int userID)
|
void Server::send(Packet& packet, UserID user)
|
||||||
{
|
{
|
||||||
int bytesSent = m_Socket.send_to(
|
int bytesSent = m_Socket.send_to(
|
||||||
boost::asio::buffer(packet.Data(), packet.Size()),
|
boost::asio::buffer(packet.Data(), packet.Size()),
|
||||||
m_ConnectedUsers[userID].Endpoint,
|
m_ConnectedUsers[user].Endpoint,
|
||||||
0);
|
0);
|
||||||
|
// Network Debug data
|
||||||
|
if (isReadingData) {
|
||||||
|
m_NetworkData.TotalDataSent += packet.Size();
|
||||||
|
m_NetworkData.DataSentThisInterval += packet.Size();
|
||||||
|
m_NetworkData.AmountOfMessagesSent++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::send(PlayerID player, Packet& packet)
|
||||||
|
{
|
||||||
|
int bytesSent = m_Socket.send_to(
|
||||||
|
boost::asio::buffer(packet.Data(), packet.Size()),
|
||||||
|
m_PlayerDefinitions[player].Endpoint,
|
||||||
|
0);
|
||||||
|
// Network Debug data
|
||||||
|
if (isReadingData) {
|
||||||
|
m_NetworkData.TotalDataSent += packet.Size();
|
||||||
|
m_NetworkData.DataSentThisInterval += packet.Size();
|
||||||
|
m_NetworkData.AmountOfMessagesSent++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::send(Packet & packet)
|
void Server::send(Packet & packet)
|
||||||
@@ -122,6 +155,11 @@ void Server::send(Packet & packet)
|
|||||||
packet.Size()),
|
packet.Size()),
|
||||||
m_ReceiverEndpoint,
|
m_ReceiverEndpoint,
|
||||||
0);
|
0);
|
||||||
|
if (isReadingData) {
|
||||||
|
// Network Debug data
|
||||||
|
m_NetworkData.TotalDataSent += packet.Size();
|
||||||
|
m_NetworkData.DataSentThisInterval += packet.Size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::broadcast(Packet& packet)
|
void Server::broadcast(Packet& packet)
|
||||||
@@ -143,9 +181,12 @@ void Server::sendSnapshot()
|
|||||||
Packet packet(MessageType::Snapshot);
|
Packet packet(MessageType::Snapshot);
|
||||||
ComponentPool* componentPool = it.second;
|
ComponentPool* componentPool = it.second;
|
||||||
ComponentInfo componentInfo = componentPool->ComponentInfo();
|
ComponentInfo componentInfo = componentPool->ComponentInfo();
|
||||||
|
|
||||||
// Component Type
|
// Component Type
|
||||||
packet.WriteString(componentInfo.Name);
|
packet.WriteString(componentInfo.Name);
|
||||||
for (auto& componentWrapper : *componentPool) {
|
for (auto& componentWrapper : *componentPool) {
|
||||||
|
// HACK: Send entity name
|
||||||
|
packet.WriteString(m_World->GetName(componentWrapper.EntityID));
|
||||||
// Components EntityID
|
// Components EntityID
|
||||||
packet.WritePrimitive(componentWrapper.EntityID);
|
packet.WritePrimitive(componentWrapper.EntityID);
|
||||||
// Parents EntityID
|
// Parents EntityID
|
||||||
@@ -160,7 +201,9 @@ void Server::sendSnapshot()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
broadcast(packet);
|
if (packet.Size() > packet.HeaderSize() + componentInfo.Name.size()) {
|
||||||
|
broadcast(packet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +217,7 @@ void Server::sendPing()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Create ping message
|
// Create ping message
|
||||||
Packet packet(MessageType::ServerPing);
|
Packet packet(MessageType::Ping);
|
||||||
packet.WriteString("Ping from server");
|
packet.WriteString("Ping from server");
|
||||||
// Time message
|
// Time message
|
||||||
m_StartPingTime = std::clock();
|
m_StartPingTime = std::clock();
|
||||||
@@ -191,7 +234,7 @@ void Server::checkForTimeOuts()
|
|||||||
if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) {
|
if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) {
|
||||||
int stopPing = 1000 * m_ConnectedUsers[i].StopTime /
|
int stopPing = 1000 * m_ConnectedUsers[i].StopTime /
|
||||||
static_cast<double>(CLOCKS_PER_SEC);
|
static_cast<double>(CLOCKS_PER_SEC);
|
||||||
if (startPing > stopPing + TIMEOUTMS) {
|
if (startPing > stopPing + m_TimeoutMs) {
|
||||||
LOG_INFO("User %i timed out!", i);
|
LOG_INFO("User %i timed out!", i);
|
||||||
disconnect(i);
|
disconnect(i);
|
||||||
}
|
}
|
||||||
@@ -199,35 +242,40 @@ void Server::checkForTimeOuts()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::disconnect(int i)
|
void Server::disconnect(UserID user)
|
||||||
{
|
{
|
||||||
//broadcast("A player disconnected");
|
//broadcast("A player disconnected");
|
||||||
LOG_INFO("User %s disconnected/timed out", m_PlayerDefinitions[i].Name.c_str());
|
LOG_INFO("User %s disconnected/timed out", m_PlayerDefinitions[user].Name.c_str());
|
||||||
// Remove enteties and stuff (When we can remove entity, remove it and tell clients to remove the copy they have)
|
// Remove enteties and stuff (When we can remove entity, remove it and tell clients to remove the copy they have)
|
||||||
m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint();
|
Events::PlayerDisconnected e;
|
||||||
m_PlayerDefinitions[i].EntityID = -1;
|
e.Entity = m_PlayerDefinitions[user].EntityID;
|
||||||
m_PlayerDefinitions[i].Name = "";
|
e.PlayerID = user;
|
||||||
m_PlayerDefinitions[i].PacketID = 0;
|
m_EventBroker->Publish(e);
|
||||||
m_ConnectedUsers.erase(m_ConnectedUsers.begin() + i);
|
|
||||||
|
m_PlayerDefinitions[user].Endpoint = boost::asio::ip::udp::endpoint();
|
||||||
|
m_PlayerDefinitions[user].EntityID = -1;
|
||||||
|
m_PlayerDefinitions[user].Name = "";
|
||||||
|
m_PlayerDefinitions[user].PacketID = 0;
|
||||||
|
m_ConnectedUsers.erase(m_ConnectedUsers.begin() + user);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::parseOnInputCommand(Packet& packet)
|
void Server::parseOnInputCommand(Packet& packet)
|
||||||
{
|
{
|
||||||
int playerID = -1;
|
PlayerID player = -1;
|
||||||
// Check which player it was who sent the message
|
// Check which player it was who sent the message
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
for (int i = 0; i < m_MaxConnections; i++) {
|
||||||
// if the player is connected set playerID to the correct PlayerID
|
// if the player is connected set playerID to the correct PlayerID
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()
|
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()
|
||||||
&& m_PlayerDefinitions[i].Endpoint.port() == m_ReceiverEndpoint.port()) {
|
&& m_PlayerDefinitions[i].Endpoint.port() == m_ReceiverEndpoint.port()) {
|
||||||
playerID = i;
|
player = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (playerID != -1) {
|
if (player != -1) {
|
||||||
while (packet.DataReadSize() < packet.Size()) {
|
while (packet.DataReadSize() < packet.Size()) {
|
||||||
Events::InputCommand e;
|
Events::InputCommand e;
|
||||||
e.Command = packet.ReadString();
|
e.Command = packet.ReadString();
|
||||||
e.PlayerID = playerID; // Set correct player id
|
e.PlayerID = player; // Set correct player id
|
||||||
e.Value = packet.ReadPrimitive<float>();
|
e.Value = packet.ReadPrimitive<float>();
|
||||||
m_EventBroker->Publish(e);
|
m_EventBroker->Publish(e);
|
||||||
//LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
//LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||||
@@ -292,17 +340,17 @@ void Server::parseDisconnect()
|
|||||||
void Server::parseClientPing()
|
void Server::parseClientPing()
|
||||||
{
|
{
|
||||||
LOG_INFO("%i: Parsing ping", m_PacketID);
|
LOG_INFO("%i: Parsing ping", m_PacketID);
|
||||||
int playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint);
|
PlayerID player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint);
|
||||||
if (playerID == -1) {
|
if (player == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Return ping
|
// Return ping
|
||||||
Packet packet(MessageType::ClientPing, m_PlayerDefinitions[playerID].PacketID);
|
Packet packet(MessageType::Ping, m_PlayerDefinitions[player].PacketID);
|
||||||
packet.WriteString("Ping received");
|
packet.WriteString("Ping received");
|
||||||
send(packet);
|
send(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::parseServerPing()
|
void Server::parsePing()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
|
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
|
||||||
if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
||||||
@@ -328,7 +376,7 @@ void Server::createPlayer()
|
|||||||
LOG_WARNING("Already connected!");
|
LOG_WARNING("Already connected!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int userIndex;
|
UserID userIndex;
|
||||||
for (userIndex = 0; userIndex < m_ConnectedUsers.size(); userIndex++) {
|
for (userIndex = 0; userIndex < m_ConnectedUsers.size(); userIndex++) {
|
||||||
if (m_ConnectedUsers[userIndex].Endpoint.address() == m_ReceiverEndpoint.address() &&
|
if (m_ConnectedUsers[userIndex].Endpoint.address() == m_ReceiverEndpoint.address() &&
|
||||||
m_ConnectedUsers[userIndex].Endpoint.port() == m_ReceiverEndpoint.port()) {
|
m_ConnectedUsers[userIndex].Endpoint.port() == m_ReceiverEndpoint.port()) {
|
||||||
@@ -340,7 +388,7 @@ void Server::createPlayer()
|
|||||||
LOG_WARNING("Not a recognized user!");
|
LOG_WARNING("Not a recognized user!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int playerIndex = 0; playerIndex < MAXCONNECTIONS; playerIndex++) {
|
for (PlayerID playerIndex = 0; playerIndex < m_MaxConnections; playerIndex++) {
|
||||||
if (m_PlayerDefinitions[playerIndex].Endpoint.address() == boost::asio::ip::address()) {
|
if (m_PlayerDefinitions[playerIndex].Endpoint.address() == boost::asio::ip::address()) {
|
||||||
m_PlayerDefinitions[playerIndex] = m_ConnectedUsers[userIndex];
|
m_PlayerDefinitions[playerIndex] = m_ConnectedUsers[userIndex];
|
||||||
EntityID entityID = m_World->CreateEntity();
|
EntityID entityID = m_World->CreateEntity();
|
||||||
@@ -358,9 +406,16 @@ void Server::createPlayer()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint)
|
void Server::kick(PlayerID player)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
disconnect(player);
|
||||||
|
Packet packet = Packet(MessageType::Kick);
|
||||||
|
send(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerID Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_MaxConnections; i++) {
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() == endpoint.address() &&
|
if (m_PlayerDefinitions[i].Endpoint.address() == endpoint.address() &&
|
||||||
m_PlayerDefinitions[i].Endpoint.port() == endpoint.port()) {
|
m_PlayerDefinitions[i].Endpoint.port() == endpoint.port()) {
|
||||||
return i;
|
return i;
|
||||||
@@ -372,5 +427,25 @@ int Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint)
|
|||||||
bool Server::OnInputCommand(const Events::InputCommand & e)
|
bool Server::OnInputCommand(const Events::InputCommand & e)
|
||||||
{
|
{
|
||||||
//LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
//LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||||
|
if (e.Command == "LogNetworkBandwidth" && e.Value > 0) {
|
||||||
|
if (isReadingData) {
|
||||||
|
saveToFile();
|
||||||
|
}
|
||||||
|
isReadingData = !isReadingData;
|
||||||
|
m_SaveDataTimer = std::clock();
|
||||||
|
}
|
||||||
|
if (e.Command == "KickPlayer" && e.Value > 0) {
|
||||||
|
kick(0);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e)
|
||||||
|
{
|
||||||
|
Packet packet = Packet(MessageType::OnPlayerSpawned);
|
||||||
|
packet.WritePrimitive<EntityID>(e.Player.ID);
|
||||||
|
packet.WritePrimitive<EntityID>(e.Spawner.ID);
|
||||||
|
send(e.PlayerID, packet);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
#include "Rendering/Font.h"
|
||||||
|
|
||||||
|
|
||||||
|
Font::Font(std::string path)
|
||||||
|
{
|
||||||
|
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
|
||||||
|
boost::char_separator<char> sep(",");
|
||||||
|
tokenizer tok(path, sep);
|
||||||
|
|
||||||
|
|
||||||
|
tokenizer::iterator it = tok.begin();
|
||||||
|
std::string filePath = "";
|
||||||
|
|
||||||
|
if (it != tok.end()) {
|
||||||
|
filePath = (*it).c_str();
|
||||||
|
it++;
|
||||||
|
if (it != tok.end()) {
|
||||||
|
if((*it).c_str() == "") {
|
||||||
|
throw std::runtime_error("");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
FontSize = boost::lexical_cast<int>((*it).c_str());
|
||||||
|
} catch (boost::bad_lexical_cast const&) {
|
||||||
|
LOG_ERROR("input string did not have a valid font resolution");
|
||||||
|
throw std::runtime_error("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("");;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FT_Library library;
|
||||||
|
FT_Face face;
|
||||||
|
|
||||||
|
if (FT_Init_FreeType(&library)) {
|
||||||
|
LOG_ERROR("FreeType error: init failed");
|
||||||
|
throw std::runtime_error("");;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FT_New_Face(library, filePath.c_str(), 0, &face)) {
|
||||||
|
LOG_ERROR("FreeType error: loading font");
|
||||||
|
throw std::runtime_error("");;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Set_Char_Size(face, 0, FontSize*64, 300, 300); // temp
|
||||||
|
FT_Set_Pixel_Sizes(face, 0, FontSize); //
|
||||||
|
|
||||||
|
if (FT_Load_Char(face, 'X', FT_LOAD_RENDER)) {
|
||||||
|
LOG_ERROR("FreeType error: loading char");
|
||||||
|
throw std::runtime_error("");;
|
||||||
|
}
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
for (GLubyte c = 0; c < 128; c++) {
|
||||||
|
|
||||||
|
|
||||||
|
//Load character glyph
|
||||||
|
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generate texture
|
||||||
|
GLuint texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
GL_RED,
|
||||||
|
face->glyph->bitmap.width,
|
||||||
|
face->glyph->bitmap.rows,
|
||||||
|
0,
|
||||||
|
GL_RED,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
face->glyph->bitmap.buffer
|
||||||
|
);
|
||||||
|
// Set texture options
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
// Now store character for later use
|
||||||
|
Character character = {
|
||||||
|
texture,
|
||||||
|
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
|
||||||
|
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
|
||||||
|
face->glyph->advance.x
|
||||||
|
};
|
||||||
|
|
||||||
|
m_Characters.insert(std::pair<GLchar, Character>(c, character));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FT_Done_Face(face);
|
||||||
|
FT_Done_FreeType(library);
|
||||||
|
GLERROR("Font Load");
|
||||||
|
}
|
||||||
|
|
||||||
|
Font::~Font()
|
||||||
|
{
|
||||||
|
for (auto c : m_Characters) {
|
||||||
|
glDeleteTextures(1, &c.second.TextureID);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,9 +47,7 @@ void PickingPass::Draw(RenderScene& scene)
|
|||||||
{
|
{
|
||||||
PickingPassState* state = new PickingPassState(m_PickingBuffer.GetHandle());
|
PickingPassState* state = new PickingPassState(m_PickingBuffer.GetHandle());
|
||||||
|
|
||||||
|
|
||||||
//TODO: Render: Add code for more jobs than modeljobs.
|
//TODO: Render: Add code for more jobs than modeljobs.
|
||||||
|
|
||||||
GLuint ShaderHandle = m_PickingProgram->GetHandle();
|
GLuint ShaderHandle = m_PickingProgram->GetHandle();
|
||||||
m_PickingProgram->Bind();
|
m_PickingProgram->Bind();
|
||||||
|
|
||||||
@@ -78,9 +76,9 @@ void PickingPass::Draw(RenderScene& scene)
|
|||||||
m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]);
|
m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]);
|
||||||
if (m_ColorCounter[0] > 255) {
|
if (m_ColorCounter[0] > 255) {
|
||||||
m_ColorCounter[0] = 0;
|
m_ColorCounter[0] = 0;
|
||||||
m_ColorCounter[1]++;;
|
m_ColorCounter[1]++;
|
||||||
} else {
|
} else {
|
||||||
m_ColorCounter[0]++;;
|
m_ColorCounter[0]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ PickingPassState::PickingPassState(GLuint frameBuffer)
|
|||||||
GLERROR("---3");
|
GLERROR("---3");
|
||||||
Enable(GL_DEPTH_TEST);
|
Enable(GL_DEPTH_TEST);
|
||||||
Enable(GL_CULL_FACE);
|
Enable(GL_CULL_FACE);
|
||||||
|
Disable(GL_BLEND);
|
||||||
|
|
||||||
glm::vec4 clearColor = glm::vec4(0.f);
|
glm::vec4 clearColor = glm::vec4(0.f);
|
||||||
//ClearColor(clearColor);
|
//ClearColor(clearColor);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRender
|
|||||||
{
|
{
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera);
|
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand);
|
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &RenderSystem::OnPlayerSpawned);
|
||||||
|
|
||||||
m_Camera = new Camera((float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, glm::radians(45.f), 0.01f, 5000.f);
|
m_Camera = new Camera((float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, glm::radians(45.f), 0.01f, 5000.f);
|
||||||
}
|
}
|
||||||
@@ -46,6 +47,13 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityWrapper entity(m_World, modelComponent.EntityID);
|
||||||
|
|
||||||
|
// Don't render the local player
|
||||||
|
if (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Model* model;
|
Model* model;
|
||||||
try {
|
try {
|
||||||
model = ResourceManager::Load<::Model, true>(resource);
|
model = ResourceManager::Load<::Model, true>(resource);
|
||||||
@@ -68,6 +76,14 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RenderSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||||
|
{
|
||||||
|
if (e.PlayerID == -1) {
|
||||||
|
m_LocalPlayer = e.Player;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void RenderSystem::fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world)
|
void RenderSystem::fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world)
|
||||||
{
|
{
|
||||||
auto pointLights = m_World->GetComponents("PointLight");
|
auto pointLights = m_World->GetComponents("PointLight");
|
||||||
@@ -110,6 +126,42 @@ void RenderSystem::fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RenderSystem::fillText(std::list<std::shared_ptr<RenderJob>>& jobs, World* world)
|
||||||
|
{
|
||||||
|
auto texts = world->GetComponents("Text");
|
||||||
|
if (texts == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& textComponent : *texts) {
|
||||||
|
bool visible = textComponent["Visible"];
|
||||||
|
if (!visible) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string resource = textComponent["Resource"];
|
||||||
|
if (resource.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Font* font;
|
||||||
|
try {
|
||||||
|
font = ResourceManager::Load<Font>(resource);
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
try {
|
||||||
|
font = ResourceManager::Load<Font>("Fonts/DroidSans.ttf,16");
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 modelMatrix = Transform::ModelMatrix(textComponent.EntityID, world);
|
||||||
|
std::shared_ptr<TextJob> modelJob = std::shared_ptr<TextJob>(new TextJob(modelMatrix, font, textComponent));
|
||||||
|
jobs.push_back(modelJob);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool RenderSystem::OnInputCommand(const Events::InputCommand& e)
|
bool RenderSystem::OnInputCommand(const Events::InputCommand& e)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -119,11 +171,12 @@ void RenderSystem::Update(double dt)
|
|||||||
{
|
{
|
||||||
m_EventBroker->Process<RenderSystem>();
|
m_EventBroker->Process<RenderSystem>();
|
||||||
|
|
||||||
if (m_CurrentCamera) {
|
// Update the current camera used for rendering
|
||||||
ComponentWrapper cameraTransform = m_CurrentCamera["Transform"];
|
if (m_CurrentCamera.Valid()) {
|
||||||
m_Camera->SetPosition(cameraTransform["Position"]);
|
m_Camera->SetPosition(Transform::AbsolutePosition(m_CurrentCamera));
|
||||||
m_Camera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"]));
|
m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Only supports opaque geometry atm
|
//Only supports opaque geometry atm
|
||||||
|
|
||||||
RenderScene scene;
|
RenderScene scene;
|
||||||
@@ -132,6 +185,7 @@ void RenderSystem::Update(double dt)
|
|||||||
fillModels(scene.ForwardJobs);
|
fillModels(scene.ForwardJobs);
|
||||||
fillPointLights(scene.PointLightJobs, m_World);
|
fillPointLights(scene.PointLightJobs, m_World);
|
||||||
fillDirectionalLights(scene.DirectionalLightJobs, m_World);
|
fillDirectionalLights(scene.DirectionalLightJobs, m_World);
|
||||||
|
fillText(scene.TextJobs, m_World);
|
||||||
m_RenderFrame->Add(scene);
|
m_RenderFrame->Add(scene);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,9 @@ void Renderer::Initialize()
|
|||||||
glfwSwapInterval(m_VSYNC);
|
glfwSwapInterval(m_VSYNC);
|
||||||
InitializeShaders();
|
InitializeShaders();
|
||||||
InitializeTextures();
|
InitializeTextures();
|
||||||
|
m_TextRenderer = new TextRenderer();
|
||||||
|
m_TextRenderer->Initialize();
|
||||||
|
|
||||||
|
|
||||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||||
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
|
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
|
||||||
@@ -77,6 +80,7 @@ void Renderer::Update(double dt)
|
|||||||
{
|
{
|
||||||
m_EventBroker->Process<Renderer>();
|
m_EventBroker->Process<Renderer>();
|
||||||
InputUpdate(dt);
|
InputUpdate(dt);
|
||||||
|
m_TextRenderer->Update();
|
||||||
m_ImGuiRenderPass->Update(dt);
|
m_ImGuiRenderPass->Update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,8 +101,12 @@ void Renderer::Draw(RenderFrame& frame)
|
|||||||
//m_DrawScenePass->Draw(rq);
|
//m_DrawScenePass->Draw(rq);
|
||||||
|
|
||||||
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
||||||
|
|
||||||
|
m_TextRenderer->Draw(*scene);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_ImGuiRenderPass->Draw();
|
m_ImGuiRenderPass->Draw();
|
||||||
glfwSwapBuffers(m_Window);
|
glfwSwapBuffers(m_Window);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
#include "Rendering/TextRenderer.h"
|
||||||
|
|
||||||
|
TextRenderer::TextRenderer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextRenderer::Initialize()
|
||||||
|
{
|
||||||
|
glGenVertexArrays(1, &VAO);
|
||||||
|
glGenBuffers(1, &VBO);
|
||||||
|
glBindVertexArray(VAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
m_TextProgram = ResourceManager::Load<ShaderProgram>("#TextProgram");
|
||||||
|
m_TextProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Text.vert.glsl")));
|
||||||
|
m_TextProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Text.frag.glsl")));
|
||||||
|
m_TextProgram->Compile();
|
||||||
|
m_TextProgram->Link();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextRenderer::Update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextRenderer::Draw(RenderScene& scene)
|
||||||
|
{
|
||||||
|
for (auto &job : scene.TextJobs) {
|
||||||
|
auto textJob = std::dynamic_pointer_cast<TextJob>(job);
|
||||||
|
if (textJob) {
|
||||||
|
|
||||||
|
renderText(textJob->Content, textJob->Resource, textJob->Alignment, textJob->Color, textJob->Matrix, scene.Camera->ProjectionMatrix(), scene.Camera->ViewMatrix());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextRenderer::renderText(std::string text, Font* font, TextJob::AlignmentEnum alignment, glm::vec4 color, glm::mat4 modelMatrix, glm::mat4 projectionMatrix, glm::mat4 viewMatrix)
|
||||||
|
{
|
||||||
|
GLfloat penX = 0;
|
||||||
|
GLfloat penY = 0;
|
||||||
|
float scale = 1.0/font->FontSize;
|
||||||
|
|
||||||
|
GLfloat stringWidth = 0.f;
|
||||||
|
|
||||||
|
for (std::string::const_iterator c = text.begin(); c != text.end(); c++) {
|
||||||
|
Font::Character ch = font->m_Characters[*c];
|
||||||
|
stringWidth += (ch.Advance >> 6) * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(alignment == TextJob::AlignmentEnum::Center) {
|
||||||
|
penX = -stringWidth/2.f;
|
||||||
|
} else if (alignment == TextJob::AlignmentEnum::Right) {
|
||||||
|
penX = -stringWidth;
|
||||||
|
} else {
|
||||||
|
penX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
m_TextProgram->Bind();
|
||||||
|
glUniform3f(glGetUniformLocation(m_TextProgram->GetHandle(), "textColor"), color.x, color.y, color.z);
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindVertexArray(VAO);
|
||||||
|
|
||||||
|
|
||||||
|
for (std::string::const_iterator c = text.begin(); c != text.end(); c++) {
|
||||||
|
Font::Character ch = font->m_Characters[*c];
|
||||||
|
|
||||||
|
GLfloat xpos = penX + ch.Bearing.x * scale;
|
||||||
|
GLfloat ypos = penY - (ch.Size.y - ch.Bearing.y) * scale;
|
||||||
|
|
||||||
|
GLfloat w = ch.Size.x * scale;
|
||||||
|
GLfloat h = ch.Size.y * scale;
|
||||||
|
|
||||||
|
GLfloat vertices[6][4] = {
|
||||||
|
{ xpos, ypos + h, 0.0, 0.0 },
|
||||||
|
{ xpos, ypos, 0.0, 1.0 },
|
||||||
|
{ xpos + w, ypos, 1.0, 1.0 },
|
||||||
|
|
||||||
|
{ xpos, ypos + h, 0.0, 0.0 },
|
||||||
|
{ xpos + w, ypos, 1.0, 1.0 },
|
||||||
|
{ xpos + w, ypos + h, 1.0, 0.0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
penX += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64)
|
||||||
|
}
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
GLERROR("Text rendering Error");
|
||||||
|
}
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ Game::Game(int argc, char* argv[])
|
|||||||
ResourceManager::RegisterType<Texture>("Texture");
|
ResourceManager::RegisterType<Texture>("Texture");
|
||||||
ResourceManager::RegisterType<ShaderProgram>("ShaderProgram");
|
ResourceManager::RegisterType<ShaderProgram>("ShaderProgram");
|
||||||
ResourceManager::RegisterType<EntityFile>("EntityFile");
|
ResourceManager::RegisterType<EntityFile>("EntityFile");
|
||||||
|
ResourceManager::RegisterType<Font>("FontFile");
|
||||||
|
|
||||||
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||||
ResourceManager::UseThreading = m_Config->Get<bool>("Multithreading.ResourceLoading", true);
|
ResourceManager::UseThreading = m_Config->Get<bool>("Multithreading.ResourceLoading", true);
|
||||||
|
|||||||
@@ -66,9 +66,6 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
|||||||
nextPossibleCapturePoint["Blue"] = -1;
|
nextPossibleCapturePoint["Blue"] = -1;
|
||||||
for (size_t i = 0; i < m_NumberOfCapturePoints; i++)
|
for (size_t i = 0; i < m_NumberOfCapturePoints; i++)
|
||||||
{
|
{
|
||||||
if (!m_World->HasComponent(m_CapturePointNumberToEntityIDMap[i], "Team")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
|
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
|
||||||
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint == 0) {
|
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint == 0) {
|
||||||
nextPossibleCapturePoint["Red"] = i + 1;
|
nextPossibleCapturePoint["Red"] = i + 1;
|
||||||
@@ -79,9 +76,6 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
|||||||
}
|
}
|
||||||
for (int i = m_NumberOfCapturePoints - 1; i >= 0; i--)
|
for (int i = m_NumberOfCapturePoints - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (!m_World->HasComponent(m_CapturePointNumberToEntityIDMap[i], "Team")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
|
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
|
||||||
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint != 0) {
|
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint != 0) {
|
||||||
nextPossibleCapturePoint["Red"] = i - 1;
|
nextPossibleCapturePoint["Red"] = i - 1;
|
||||||
|
|||||||
@@ -1,24 +1,14 @@
|
|||||||
#include "Systems/InterpolationSystem.h"
|
#include "Systems/InterpolationSystem.h"
|
||||||
|
|
||||||
//void InterpolationSystem::UpdateComponent(World * world, ComponentWrapper & transform, double dt)
|
InterpolationSystem::InterpolationSystem(World* world, EventBroker* eventBroker)
|
||||||
//{
|
: System(world, eventBroker)
|
||||||
// if (m_InterpolationPoints[transform.EntityID].size() > 0) {
|
, PureSystem("Transform")
|
||||||
// Transform& sTransform = m_InterpolationPoints[transform.EntityID].front();
|
{
|
||||||
// sTransform.interpolationTime += dt;
|
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||||
// if (sTransform.interpolationTime > 0.05) {
|
m_SnapshotInterval = config->Get<float>("Networking.SnapshotInterval", 0.05);
|
||||||
// double time = std::fmod(sTransform.interpolationTime, 0.05f);
|
EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate);
|
||||||
// m_InterpolationPoints[transform.EntityID].pop();
|
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &InterpolationSystem::OnPlayerSpawned);
|
||||||
// if (m_InterpolationPoints[transform.EntityID].size() <= 0) {
|
}
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// sTransform = m_InterpolationPoints[transform.EntityID].front();
|
|
||||||
// sTransform.interpolationTime = time;
|
|
||||||
// }
|
|
||||||
// glm::vec3 nextPosition = sTransform.Position;
|
|
||||||
// glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
|
|
||||||
// transform["Position"] = vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt)
|
void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt)
|
||||||
{
|
{
|
||||||
@@ -26,10 +16,10 @@ void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrappe
|
|||||||
m_NextTransform[transform.EntityID].interpolationTime += dt;
|
m_NextTransform[transform.EntityID].interpolationTime += dt;
|
||||||
Transform sTransform = m_NextTransform[transform.EntityID];
|
Transform sTransform = m_NextTransform[transform.EntityID];
|
||||||
double time = sTransform.interpolationTime;
|
double time = sTransform.interpolationTime;
|
||||||
if (time > SNAPSHOTINTERVAL) {
|
if (time > m_SnapshotInterval) {
|
||||||
if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) {
|
if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) {
|
||||||
m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID];
|
m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID];
|
||||||
m_NextTransform[transform.EntityID].interpolationTime = time - SNAPSHOTINTERVAL;
|
m_NextTransform[transform.EntityID].interpolationTime = time - m_SnapshotInterval;
|
||||||
sTransform = m_NextTransform[transform.EntityID];
|
sTransform = m_NextTransform[transform.EntityID];
|
||||||
m_LastReceivedTransform.erase(transform.EntityID);
|
m_LastReceivedTransform.erase(transform.EntityID);
|
||||||
} else {
|
} else {
|
||||||
@@ -37,14 +27,22 @@ void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transform.Info.Name == "Transform") {
|
if (transform.Info.Name == "Transform") {
|
||||||
|
bool isLocalPlayer = entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer);
|
||||||
// Position
|
// Position
|
||||||
glm::vec3 nextPosition = sTransform.Position;
|
glm::vec3 nextPosition = sTransform.Position;
|
||||||
glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
|
glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
|
||||||
|
// HACK: Hardcoded tolerance value for player position desync = 1
|
||||||
|
if (isLocalPlayer && glm::length(nextPosition - currentPosition) < 1.f) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
(glm::vec3&)transform["Position"] += vectorInterpolation<glm::vec3>(currentPosition, nextPosition, sTransform.interpolationTime);
|
(glm::vec3&)transform["Position"] += vectorInterpolation<glm::vec3>(currentPosition, nextPosition, sTransform.interpolationTime);
|
||||||
// Orientation
|
// Orientation
|
||||||
glm::quat nextOrientation = sTransform.Orientation;
|
// Don't force orientation for players
|
||||||
glm::quat currentOrientation = glm::quat(static_cast<glm::vec3>(transform["Orientation"]));
|
if (!isLocalPlayer) {
|
||||||
(glm::vec3&)transform["Orientation"] = glm::eulerAngles(glm::slerp<float>(currentOrientation, nextOrientation, sTransform.interpolationTime / SNAPSHOTINTERVAL));
|
glm::quat nextOrientation = sTransform.Orientation;
|
||||||
|
glm::quat currentOrientation = glm::quat(static_cast<glm::vec3>(transform["Orientation"]));
|
||||||
|
(glm::vec3&)transform["Orientation"] = glm::eulerAngles(glm::slerp<float>(currentOrientation, nextOrientation, sTransform.interpolationTime / m_SnapshotInterval));
|
||||||
|
}
|
||||||
// Scale
|
// Scale
|
||||||
glm::vec3 nextScale = sTransform.Scale;
|
glm::vec3 nextScale = sTransform.Scale;
|
||||||
glm::vec3 currentScale = static_cast<glm::vec3>(transform["Scale"]);
|
glm::vec3 currentScale = static_cast<glm::vec3>(transform["Scale"]);
|
||||||
@@ -53,6 +51,12 @@ void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterpolationSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||||
|
{
|
||||||
|
m_LocalPlayer = e.Player;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e)
|
bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e)
|
||||||
{
|
{
|
||||||
Transform transform;
|
Transform transform;
|
||||||
@@ -72,15 +76,5 @@ bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e)
|
|||||||
} else { // Did not
|
} else { // Did not
|
||||||
m_NextTransform[e.Entity] = transform;
|
m_NextTransform[e.Entity] = transform;
|
||||||
}
|
}
|
||||||
// Check if queue already exists
|
|
||||||
//if (m_InterpolationPoints.find(e.Entity) != m_InterpolationPoints.end()) { // Did exist, push to queue
|
|
||||||
// m_InterpolationPoints[e.Entity].push(transform);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//else { // Did not exist, create queue
|
|
||||||
// std::queue<Transform> transformQueue;
|
|
||||||
// transformQueue.push(transform);
|
|
||||||
// m_InterpolationPoints[e.Entity] = transformQueue;
|
|
||||||
//}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,55 @@
|
|||||||
#include "Systems/PlayerMovementSystem.h"
|
#include "Systems/PlayerMovementSystem.h"
|
||||||
|
|
||||||
|
PlayerMovementSystem::PlayerMovementSystem(World* world, EventBroker* eventBroker)
|
||||||
|
: System(world, eventBroker)
|
||||||
|
, PureSystem("Player")
|
||||||
|
{
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &PlayerMovementSystem::OnPlayerSpawned);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerMovementSystem::~PlayerMovementSystem()
|
||||||
|
{
|
||||||
|
for (auto& kv : m_PlayerInputControllers) {
|
||||||
|
delete kv.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerMovementSystem::Update(double dt)
|
||||||
|
{
|
||||||
|
for (auto& kv : m_PlayerInputControllers) {
|
||||||
|
EntityWrapper player = kv.first;
|
||||||
|
auto& controller = kv.second;
|
||||||
|
|
||||||
|
if (!player.Valid()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityWrapper cameraEntity = player.FirstChildByName("Camera");
|
||||||
|
if (cameraEntity.Valid()) {
|
||||||
|
glm::vec3& cameraOrientation = cameraEntity["Transform"]["Orientation"];
|
||||||
|
cameraOrientation.x += controller->Rotation().x;
|
||||||
|
// Limit camera pitch so we don't break our necks
|
||||||
|
cameraOrientation.x = glm::clamp(cameraOrientation.x, -glm::half_pi<float>(), glm::half_pi<float>());
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentWrapper& cTransform = player["Transform"];
|
||||||
|
glm::vec3& ori = cTransform["Orientation"];
|
||||||
|
ori.y += controller->Rotation().y;
|
||||||
|
|
||||||
|
glm::vec3& pos = cTransform["Position"];
|
||||||
|
pos += controller->Movement() * glm::inverse(glm::quat(ori)) * (float)player["Player"]["MovementSpeed"] * (float)dt;
|
||||||
|
|
||||||
|
if (player.HasComponent("Physics")) {
|
||||||
|
if (controller->Jumping()) {
|
||||||
|
glm::vec3& velocity = player["Physics"]["Velocity"];
|
||||||
|
velocity.y += 10.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||||
{
|
{
|
||||||
ComponentWrapper& cTransform = entity["Transform"];
|
ComponentWrapper& cTransform = entity["Transform"];
|
||||||
@@ -10,9 +60,17 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
|
|||||||
|
|
||||||
glm::vec3& velocity = cPhysics["Velocity"];
|
glm::vec3& velocity = cPhysics["Velocity"];
|
||||||
if (cPhysics["Gravity"]) {
|
if (cPhysics["Gravity"]) {
|
||||||
velocity.y -= 9.82 * dt;
|
velocity.y -= 9.82f * (float)dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3& position = cTransform["Position"];
|
glm::vec3& position = cTransform["Position"];
|
||||||
position += velocity * (float)dt;
|
position += velocity * (float)dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||||
|
{
|
||||||
|
// When a player spawns, create an input controller for them
|
||||||
|
m_PlayerInputControllers[e.Player] = new FirstPersonInputController<PlayerMovementSystem>(m_EventBroker, e.PlayerID);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ PlayerSpawnSystem::PlayerSpawnSystem(World* m_World, EventBroker* eventBroker)
|
|||||||
: System(m_World, eventBroker)
|
: System(m_World, eventBroker)
|
||||||
{
|
{
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand);
|
EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerSpawnerd, &PlayerSpawnSystem::OnPlayerSpawned);
|
||||||
|
m_NetworkEnabled = ResourceManager::Load<ConfigFile>("Config.ini")->Get("Networking.StartNetwork", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerSpawnSystem::Update(double dt)
|
void PlayerSpawnSystem::Update(double dt)
|
||||||
@@ -13,7 +15,7 @@ void PlayerSpawnSystem::Update(double dt)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& team : m_SpawnRequests) {
|
for (auto& req : m_SpawnRequests) {
|
||||||
for (auto& cPlayerSpawn : *playerSpawns) {
|
for (auto& cPlayerSpawn : *playerSpawns) {
|
||||||
EntityWrapper spawner(m_World, cPlayerSpawn.EntityID);
|
EntityWrapper spawner(m_World, cPlayerSpawn.EntityID);
|
||||||
if (!spawner.HasComponent("Spawner")) {
|
if (!spawner.HasComponent("Spawner")) {
|
||||||
@@ -22,7 +24,7 @@ void PlayerSpawnSystem::Update(double dt)
|
|||||||
|
|
||||||
// If the spawner has a team affiliation, check it
|
// If the spawner has a team affiliation, check it
|
||||||
if (spawner.HasComponent("Team")) {
|
if (spawner.HasComponent("Team")) {
|
||||||
if ((int)spawner["Team"]["Team"] != team) {
|
if ((int)spawner["Team"]["Team"] != req.Team) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +32,15 @@ void PlayerSpawnSystem::Update(double dt)
|
|||||||
// Spawn the player!
|
// Spawn the player!
|
||||||
EntityWrapper player = SpawnerSystem::Spawn(spawner);
|
EntityWrapper player = SpawnerSystem::Spawn(spawner);
|
||||||
// Set the player team affiliation
|
// Set the player team affiliation
|
||||||
player["Team"]["Team"] = team;
|
player["Team"]["Team"] = req.Team;
|
||||||
|
|
||||||
|
// Publish a PlayerSpawned event
|
||||||
|
Events::PlayerSpawned e;
|
||||||
|
e.PlayerID = req.PlayerID;
|
||||||
|
e.Player = player;
|
||||||
|
e.Spawner = spawner;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_SpawnRequests.clear();
|
m_SpawnRequests.clear();
|
||||||
@@ -42,10 +52,33 @@ bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Team picks should be processed ONLY server-side!
|
||||||
|
// Don't make a spawn request if PlayerID is -1, i.e. we're the client.
|
||||||
|
if (e.PlayerID == -1 && m_NetworkEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.Value != 0) {
|
if (e.Value != 0) {
|
||||||
m_SpawnRequests.push_back((int)e.Value);
|
SpawnRequest req;
|
||||||
|
req.PlayerID = e.PlayerID;
|
||||||
|
req.Team = (ComponentInfo::EnumType)e.Value;
|
||||||
|
m_SpawnRequests.push_back(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||||
|
{
|
||||||
|
// When a player is actually spawned (since the actual spawning is handled on the server)
|
||||||
|
|
||||||
|
// Set the camera to the correct entity
|
||||||
|
EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera");
|
||||||
|
if (cameraEntity.Valid()) {
|
||||||
|
Events::SetCamera e;
|
||||||
|
e.CameraEntity = cameraEntity;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user