From 236230d12c77473c22aeef9df7fdc8fc750a33b6 Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 12 Jan 2016 12:00:19 +0100 Subject: [PATCH] Packets now dynamically allocates more memory when they need it. Increased local receive buffer for Client and Server() and removed the magic number that was used In Server.h and Client.h (char readBuffer[INPUTSIZE] = { 0 }). Packets start size has now been increased to 512 bytes. Changed ComponentInfo::FieldsInOrder to store strings instead of pointers. Removed HasEntity() and are now using ValidEntity() instead. --- include/Engine/Core/ComponentInfo.h | 3 +- include/Engine/Core/World.h | 2 - include/Engine/Network/Client.h | 5 +- include/Engine/Network/Network.h | 2 +- include/Engine/Network/Packet.h | 9 +- include/Engine/Network/Server.h | 3 +- src/Engine/Collision/Collision.cpp | 392 ++++++++++----------- src/Engine/Core/EntityFilePreprocessor.cpp | 3 +- src/Engine/Core/World.cpp | 8 +- src/Engine/Network/Client.cpp | 53 +-- src/Engine/Network/Packet.cpp | 32 +- src/Engine/Network/Server.cpp | 119 +------ src/Game/Game.cpp | 32 +- 13 files changed, 307 insertions(+), 356 deletions(-) diff --git a/include/Engine/Core/ComponentInfo.h b/include/Engine/Core/ComponentInfo.h index abf4ff15..985a057e 100644 --- a/include/Engine/Core/ComponentInfo.h +++ b/include/Engine/Core/ComponentInfo.h @@ -14,6 +14,7 @@ struct ComponentInfo struct Field_t { + std::string Name; std::string Type; unsigned int Offset; unsigned int Stride; @@ -21,7 +22,7 @@ struct ComponentInfo std::string Name; std::unordered_map Fields; - std::vector FieldsInOrder; + std::vector FieldsInOrder; Meta_t Meta; std::shared_ptr Defaults = nullptr; }; diff --git a/include/Engine/Core/World.h b/include/Engine/Core/World.h index c066933a..0a121728 100644 --- a/include/Engine/Core/World.h +++ b/include/Engine/Core/World.h @@ -22,8 +22,6 @@ public: void RegisterComponent(ComponentInfo& ci); // Attach a component to an entity and fill it with default values ComponentWrapper AttachComponent(EntityID entity, std::string componentType); - // Check if world has an entity - bool HasEntity(EntityID entity); // Check if an entity has a component bool HasComponent(EntityID entity, std::string componentType) const; // Get a component of an entity diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 95888b1f..b7bd9b38 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -32,7 +32,7 @@ private: // Sending message to server logic int bytesRead = -1; - char readBuf[1024] = { 0 }; + char readBuf[INPUTSIZE] = { 0 }; int snapshotInterval = 33; std::clock_t previousSnapshotMessage = std::clock(); @@ -59,7 +59,7 @@ private: // Private member functions void readFromServer(); void sendSnapshotToServer(); - int receive(char* data, size_t length); + int receive(char* data, size_t length); void send(Packet& packet); void connect(); void disconnect(); @@ -67,6 +67,7 @@ private: void moveMessageHead(char*& data, size_t& length, size_t stepSize); void parseMessageType(Packet& packet); void parseEventMessage(Packet& packet); + void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); void parseConnect(Packet& packet); void parsePing(); void parseServerPing(); diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index c5107b2b..8a50f061 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -6,7 +6,7 @@ #include "Network/Packet.h" #define MAXCONNECTIONS 8 -#define INPUTSIZE 128 +#define INPUTSIZE 4097 class Network { diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index 76cf2cba..112ebe34 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -23,8 +23,8 @@ public: { // Check if we are trying to add more than the package can fit. if (m_MaxPacketSize < m_Offset + sizeof(T)) { - LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for!"); - return; + LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for! New size is %i bytes\n", m_MaxPacketSize*2); + resizeData(); } memcpy(m_Data + m_Offset, &val, sizeof(T)); m_Offset += sizeof(T); @@ -43,7 +43,7 @@ public: return returnValue; } // Add a string to the message - void WriteString(std::string str); + void WriteString(const std::string& str); // Add data to the message void WriteData(char* data, int sizeOfData); // Pops the first element as if it was a string. @@ -59,7 +59,8 @@ private: char* m_Data; unsigned int m_ReturnDataOffset = 0; int m_Offset = 0; - unsigned int m_MaxPacketSize = 128; + unsigned int m_MaxPacketSize = 512; + void resizeData(); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index af454bc1..58ee2631 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -30,7 +30,7 @@ private: PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; // Sending messages to client logic - char readBuffer[1024] = { 0 }; + char readBuffer[INPUTSIZE] = { 0 }; int bytesRead = 0; // time for previouse message std::clock_t previousePingMessage = std::clock(); @@ -67,7 +67,6 @@ private: void moveMessageHead(char*& data, size_t& length, size_t stepSize); void broadcast(std::string message); void broadcast(Packet& packet); - //void parseShitTest(Packet& packet); // Remove this when network is working void sendSnapshot(); void sendPing(); void checkForTimeOuts(); diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index a767ee95..620e9639 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -8,196 +8,196 @@ namespace Collision { - //note: this one hasnt been delta adjusted like RayVsAABB has - bool RayAABBIntr(const Ray& ray, const AABB& box) - { - glm::vec3 w = 75.0f * ray.Direction(); - glm::vec3 v = glm::abs(w); - glm::vec3 c = ray.Origin() - box.Center() + w; - glm::vec3 half = box.HalfSize(); +//note: this one hasnt been delta adjusted like RayVsAABB has +bool RayAABBIntr(const Ray& ray, const AABB& box) +{ + glm::vec3 w = 75.0f * ray.Direction(); + glm::vec3 v = glm::abs(w); + glm::vec3 c = ray.Origin() - box.Center() + w; + glm::vec3 half = box.HalfSize(); - if (abs(c.x) > v.x + half.x) { - return false; - } - if (abs(c.y) > v.y + half.y) { - return false; - } - if (abs(c.z) > v.z + half.z) { - return false; - } - - if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) { - return false; - } - if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) { - return false; - } - return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x); + if (abs(c.x) > v.x + half.x) { + return false; } - - bool RayVsAABB(const Ray& ray, const AABB& box) - { - float dummy; - return RayVsAABB(ray, box, dummy); + if (abs(c.y) > v.y + half.y) { + return false; } - - bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance) - { - glm::vec3 invdir = 1.0f / ray.Direction(); - glm::vec3 origin = ray.Origin(); - - float t1 = (box.MinCorner().x - origin.x)*invdir.x; - float t2 = (box.MaxCorner().x - origin.x)*invdir.x; - float t3 = (box.MinCorner().y - origin.y)*invdir.y; - float t4 = (box.MaxCorner().y - origin.y)*invdir.y; - float t5 = (box.MinCorner().z - origin.z)*invdir.z; - float t6 = (box.MaxCorner().z - origin.z)*invdir.z; - - float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); - float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); - - //if (tmax < 0 || tmin > tmax) - //if tmin,tmax are almost the same (i.e. hitting exactly in the corner) then tmin might be slightly - //greater than tmax becuase of floating-precision problems. fixed by adding a small delta to tmax - if (tmax < 0 || tmin>(tmax + 0.0001f)) - return false; - - outDistance = (tmin > 0) ? tmin : tmax; - return true; - } - - bool AABBVsAABB(const AABB& a, const AABB& b) - { - const glm::vec3& aCenter = a.Center(); - const glm::vec3& bCenter = b.Center(); - const glm::vec3& aHSize = a.HalfSize(); - const glm::vec3& bHSize = b.HalfSize(); - //Test will probably exit because of the X and Z axes more often, so test them first. - if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) { - return false; - } - if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) { - return false; - } - return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1])); - } - - bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation) - { - minimumTranslation = glm::vec3(0, 0, 0); - const glm::vec3& aMax = a.MaxCorner(); - const glm::vec3& bMax = b.MaxCorner(); - const glm::vec3& aMin = a.MinCorner(); - const glm::vec3& bMin = b.MinCorner(); - const glm::vec3& bSize = b.Size(); - const glm::vec3& aSize = a.Size(); - float minOffset = INFINITY; - float off; - auto axisesIntersecting = glm::tvec3(false, false, false); - for (int i = 0; i < 3; ++i) { - off = bMax[i] - aMin[i]; - if (off > 0 && off < bSize[i] + aSize[i]) { - if (off < minOffset) { - minimumTranslation = glm::vec3(); - minimumTranslation[i] = minOffset = off; - } - axisesIntersecting[i] = true; - } - off = aMax[i] - bMin[i]; - if (off > 0 && off < bSize[i] + aSize[i]) { - if (off < minOffset) { - minOffset = off; - minimumTranslation = glm::vec3(); - minimumTranslation[i] = -off; - } - axisesIntersecting[i] = true; - } - } - return glm::all(axisesIntersecting); - } - - bool RayVsModel(const Ray& ray, - const std::vector& modelVertices, - const std::vector& modelIndices) - { - for (int i = 0; i < modelIndices.size(); ++i) { - glm::vec3 v0 = modelVertices[modelIndices[i]].Position; - glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 - glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 - glm::vec3 m = ray.Origin() - v0; - glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction(), e2); - float DetInv = glm::dot(e1, DxE2); - if (std::abs(DetInv) < FLT_EPSILON) { - continue; - } - DetInv = 1.0f / DetInv; - float u = glm::dot(m, DxE2) * DetInv; - float v = glm::dot(ray.Direction(), MxE1) * DetInv; - //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem - if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) { - continue; - } - //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. - if (0 <= glm::dot(e2, MxE1) * DetInv) { - return true; - } - } + if (abs(c.z) > v.z + half.z) { return false; } - bool RayVsModel(const Ray& ray, - const std::vector& modelVertices, - const std::vector& modelIndices, - float& outDistance, - float& outUCoord, - float& outVCoord) - { - outDistance = INFINITY; - bool hit = false; - for (int i = 0; i < modelIndices.size(); ++i) { - glm::vec3 v0 = modelVertices[modelIndices[i]].Position; - glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 - glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 - glm::vec3 m = ray.Origin() - v0; - glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec - float DetInv = glm::dot(e1, DxE2); - if (std::abs(DetInv) < FLT_EPSILON) { - continue; - } - DetInv = 1.0f / DetInv; - float dist = glm::dot(e2, MxE1) * DetInv; - if (dist >= outDistance) { - continue; - } - float u = glm::dot(m, DxE2) * DetInv; - float v = glm::dot(ray.Direction(), MxE1) * DetInv; + if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) { + return false; + } + if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) { + return false; + } + return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x); +} - //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem - //If u and v are positive, u+v <= 1, dist is positive, and less than closest. - if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) { - outDistance = dist; - outUCoord = u; - outVCoord = v; - hit = true; +bool RayVsAABB(const Ray& ray, const AABB& box) +{ + float dummy; + return RayVsAABB(ray, box, dummy); +} + +bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance) +{ + glm::vec3 invdir = 1.0f / ray.Direction(); + glm::vec3 origin = ray.Origin(); + + float t1 = (box.MinCorner().x - origin.x)*invdir.x; + float t2 = (box.MaxCorner().x - origin.x)*invdir.x; + float t3 = (box.MinCorner().y - origin.y)*invdir.y; + float t4 = (box.MaxCorner().y - origin.y)*invdir.y; + float t5 = (box.MinCorner().z - origin.z)*invdir.z; + float t6 = (box.MaxCorner().z - origin.z)*invdir.z; + + float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); + float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); + + //if (tmax < 0 || tmin > tmax) + //if tmin,tmax are almost the same (i.e. hitting exactly in the corner) then tmin might be slightly + //greater than tmax becuase of floating-precision problems. fixed by adding a small delta to tmax + if (tmax < 0 || tmin>(tmax + 0.0001f)) + return false; + + outDistance = (tmin > 0) ? tmin : tmax; + return true; +} + +bool AABBVsAABB(const AABB& a, const AABB& b) +{ + const glm::vec3& aCenter = a.Center(); + const glm::vec3& bCenter = b.Center(); + const glm::vec3& aHSize = a.HalfSize(); + const glm::vec3& bHSize = b.HalfSize(); + //Test will probably exit because of the X and Z axes more often, so test them first. + if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) { + return false; + } + if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) { + return false; + } + return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1])); +} + +bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation) +{ + minimumTranslation = glm::vec3(0, 0, 0); + const glm::vec3& aMax = a.MaxCorner(); + const glm::vec3& bMax = b.MaxCorner(); + const glm::vec3& aMin = a.MinCorner(); + const glm::vec3& bMin = b.MinCorner(); + const glm::vec3& bSize = b.Size(); + const glm::vec3& aSize = a.Size(); + float minOffset = INFINITY; + float off; + auto axisesIntersecting = glm::tvec3(false, false, false); + for (int i = 0; i < 3; ++i) { + off = bMax[i] - aMin[i]; + if (off > 0 && off < bSize[i] + aSize[i]) { + if (off < minOffset) { + minimumTranslation = glm::vec3(); + minimumTranslation[i] = minOffset = off; } + axisesIntersecting[i] = true; + } + off = aMax[i] - bMin[i]; + if (off > 0 && off < bSize[i] + aSize[i]) { + if (off < minOffset) { + minOffset = off; + minimumTranslation = glm::vec3(); + minimumTranslation[i] = -off; + } + axisesIntersecting[i] = true; } - return hit; } + return glm::all(axisesIntersecting); +} - bool RayVsModel(const Ray& ray, - const std::vector& modelVertices, - const std::vector& modelIndices, - glm::vec3& outHitPosition) - { - float u; - float v; - float dist; - bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v); - outHitPosition = ray.Origin() + dist * ray.Direction(); - return hit; +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices) +{ + for (int i = 0; i < modelIndices.size(); ++i) { + glm::vec3 v0 = modelVertices[modelIndices[i]].Position; + glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 + glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 + glm::vec3 m = ray.Origin() - v0; + glm::vec3 MxE1 = glm::cross(m, e1); + glm::vec3 DxE2 = glm::cross(ray.Direction(), e2); + float DetInv = glm::dot(e1, DxE2); + if (std::abs(DetInv) < FLT_EPSILON) { + continue; + } + DetInv = 1.0f / DetInv; + float u = glm::dot(m, DxE2) * DetInv; + float v = glm::dot(ray.Direction(), MxE1) * DetInv; + //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem + if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) { + continue; + } + //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. + if (0 <= glm::dot(e2, MxE1) * DetInv) { + return true; + } } + return false; +} + +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices, + float& outDistance, + float& outUCoord, + float& outVCoord) +{ + outDistance = INFINITY; + bool hit = false; + for (int i = 0; i < modelIndices.size(); ++i) { + glm::vec3 v0 = modelVertices[modelIndices[i]].Position; + glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 + glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 + glm::vec3 m = ray.Origin() - v0; + glm::vec3 MxE1 = glm::cross(m, e1); + glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec + float DetInv = glm::dot(e1, DxE2); + if (std::abs(DetInv) < FLT_EPSILON) { + continue; + } + DetInv = 1.0f / DetInv; + float dist = glm::dot(e2, MxE1) * DetInv; + if (dist >= outDistance) { + continue; + } + float u = glm::dot(m, DxE2) * DetInv; + float v = glm::dot(ray.Direction(), MxE1) * DetInv; + + //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem + //If u and v are positive, u+v <= 1, dist is positive, and less than closest. + if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) { + outDistance = dist; + outUCoord = u; + outVCoord = v; + hit = true; + } + } + return hit; +} + +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices, + glm::vec3& outHitPosition) +{ + float u; + float v; + float dist; + bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v); + outHitPosition = ray.Origin() + dist * ray.Direction(); + return hit; +} bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) { @@ -245,29 +245,23 @@ bool attachAABBComponentFromModel(World* world, EntityID id) bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox) { - if (world->HasComponent(AABBComponent.EntityID, "Transform") && world->HasComponent(AABBComponent.EntityID, "Model")) - { - ComponentWrapper& cTrans = world->GetComponent(AABBComponent.EntityID, "Transform"); - ComponentWrapper model = world->GetComponent(AABBComponent.EntityID, "Model"); - if(AABBComponent.EntityID == 3); - std::string checkPath = model["Resource"]; - Model* modelRes = ResourceManager::Load(model["Resource"]); - outBox.CreateFromCenter(AABBComponent["BoxCenter"], AABBComponent["BoxSize"]); - glm::vec3 mini = outBox.MinCorner(); - glm::vec3 maxi = outBox.MaxCorner(); + ComponentWrapper& cTrans = world->GetComponent(AABBComponent.EntityID, "Transform"); + ComponentWrapper model = world->GetComponent(AABBComponent.EntityID, "Model"); + Model* modelRes = ResourceManager::Load(model["Resource"]); + outBox.CreateFromCenter(AABBComponent["BoxCenter"], AABBComponent["BoxSize"]); + glm::vec3 mini = outBox.MinCorner(); + glm::vec3 maxi = outBox.MaxCorner(); - if (modelRes == nullptr) { - return false; - } - glm::mat4 modelMatrix = modelRes->m_Matrix * - glm::translate(glm::mat4(), (glm::vec3)cTrans["Position"]) * - glm::scale((glm::vec3)cTrans["Scale"]); - - outBox = AABB(modelMatrix * glm::vec4(mini.x, mini.y, mini.z, 1), - modelMatrix * glm::vec4(maxi.x, maxi.y, maxi.z, 1)); - return true; + if (modelRes == nullptr) { + return false; } - return false; + glm::mat4 modelMatrix = modelRes->m_Matrix * + glm::translate(glm::mat4(), (glm::vec3)cTrans["Position"]) * + glm::scale((glm::vec3)cTrans["Scale"]); + + outBox = AABB(modelMatrix * glm::vec4(mini.x, mini.y, mini.z, 1), + modelMatrix * glm::vec4(maxi.x, maxi.y, maxi.z, 1)); + return true; } bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel) diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityFilePreprocessor.cpp index 83e2fe28..ca445042 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityFilePreprocessor.cpp @@ -144,10 +144,11 @@ void EntityFilePreprocessor::parseComponentInfo() } auto& field = compInfo.Fields[name]; + field.Name = name; field.Type = type; field.Offset = fieldOffset; field.Stride = stride; - compInfo.FieldsInOrder.push_back(&field); + compInfo.FieldsInOrder.push_back(name); fieldOffset += stride; } diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index faddeb83..c94cb8b3 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -80,13 +80,7 @@ ComponentWrapper World::AttachComponent(EntityID entity, std::string componentTy return c; } -bool World::HasEntity(EntityID entity) -{ - return m_EntityParents.find(entity) != m_EntityParents.end(); -} - - -bool World::HasComponent(EntityID entity, std::string componentType) +bool World::HasComponent(EntityID entity, std::string componentType) const { ComponentPool* pool = m_ComponentPools.at(componentType); return pool->KnowsEntity(entity); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 08f68f98..e682297e 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -27,8 +27,6 @@ void Client::Start(World* world, EventBroker* eventBroker) m_World = world; // Subscribe to events - //m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1)); - //m_EventBroker->Subscribe(m_EInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand); m_Socket.connect(m_ReceiverEndpoint); @@ -74,7 +72,6 @@ void Client::sendSnapshotToServer() auto player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player"); - // See if any movement keys are down // We dont care if it's overwritten by later // if statement. Watcha gonna do, right! @@ -181,47 +178,53 @@ void Client::parseEventMessage(Packet& packet) } } +void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType) +{ + for (auto field : componentInfo.FieldsInOrder) { + ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field); + if (fieldInfo.Type == "string") { + std::string& value = packet.ReadString(); + m_World->GetComponent(entityID, componentType)[fieldInfo.Name] = value; + } else { + memcpy(m_World->GetComponent(entityID, componentType).Data + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride); + } + } +} + +// Field parse void Client::parseSnapshot(Packet& packet) { std::string componentType = packet.ReadString(); - //LOG_INFO("A snapshot was parsed. first component type is: %s", componentType.c_str()); - int stride = packet.ReadPrimitive(); - int nrOfComponents = (packet.Size() - packet.DataReadSize()) / (stride + sizeof(EntityID)); - if (componentType == "Model") - return; - for (size_t i = 0; i < nrOfComponents; i++) { + while (packet.DataReadSize() < packet.Size()) { EntityID entityID = packet.ReadPrimitive(); - //ComponentWrapper model = m_World->GetComponent(entityID, "Model"); - //std::string checkPath = model["Resource"]; - // Check if entity exists - if (m_World->HasEntity(entityID)) { - // check if component exists + ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo(); + if (m_World->ValidEntity(entityID)) { if (m_World->HasComponent(entityID, componentType)) { - //Copy data to component - memcpy(m_World->GetComponent(entityID, componentType).Data, packet.ReadData(stride), stride); + // If the entity and the component exists update it + updateFields(packet, componentInfo, entityID, componentType); + // if entity exists but not the component } else { - // If component doesen't exist // Create component m_World->AttachComponent(entityID, componentType); // Copy data to newly created component - memcpy(m_World->GetComponent(entityID, componentType).Data, packet.ReadData(stride), stride); + updateFields(packet, componentInfo, entityID, componentType); } + // If the entity dosent exist nor the component } else { + //Create Entity // If entity dosen't exist EntityID newEntityID = m_World->CreateEntity(); // Check if EntityIDs are out of sync if (newEntityID != entityID) { - LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the same as the one sent by server \ - EntityIDs are out of sync"); + LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \ + same as the one sent by server (EntityIDs are out of sync)"); } + // Create component m_World->AttachComponent(newEntityID, componentType); // Copy data to newly created component - memcpy(m_World->GetComponent(entityID, componentType).Data, packet.ReadData(stride), stride); + updateFields(packet, componentInfo, newEntityID, componentType); } - //ComponentWrapper model2 = m_World->GetComponent(entityID, "Model"); - //std::string checkPath2 = model2["Resource"]; } - } int Client::receive(char* data, size_t length) @@ -234,7 +237,7 @@ int Client::receive(char* data, size_t length) 0, error); if (error) { - //LOG_ERROR("receive: %s", error.message().c_str()); + LOG_ERROR("receive: %s", error.message().c_str()); } return bytesReceived; diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 86a91f5d..2b2c7938 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -35,13 +35,13 @@ void Packet::Init(MessageType type, unsigned int & packetID) packetID++; } -void Packet::WriteString(std::string str) +void Packet::WriteString(const std::string& str) { // Message, add one extra byte for null terminator int sizeOfString = str.size() + 1; if (m_Offset + sizeOfString > m_MaxPacketSize) { - LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size.\n"); - return; + LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2); + resizeData(); } memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char)); m_Offset += sizeOfString * sizeof(char); @@ -50,8 +50,8 @@ void Packet::WriteString(std::string str) void Packet::WriteData(char * data, int sizeOfData) { if (m_Offset + sizeOfData > m_MaxPacketSize) { - LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size.\n"); - return; + LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2); + resizeData(); } memcpy(m_Data + m_Offset, data, sizeOfData); m_Offset += sizeOfData; @@ -78,4 +78,24 @@ char * Packet::ReadData(int SizeOfData) unsigned int oldReturnDataOffset = m_ReturnDataOffset; m_ReturnDataOffset += SizeOfData; return (m_Data + oldReturnDataOffset); -} \ No newline at end of file +} + +void Packet::resizeData() +{ + + // Allocate memory to store our data in + char* holdData = new char[m_MaxPacketSize]; + // Copy our data to the newly allocated memory + memcpy(holdData, m_Data, m_Offset); + // Increase max packet size + m_MaxPacketSize = m_MaxPacketSize * 2; + // Delete our data + delete m_Data; + // Allocate twice the memory we had before + m_Data = new char[m_MaxPacketSize]; + // Copy our data to new location + memcpy(m_Data, holdData, m_Offset); + // Delete the memory allocated to hold our data + // while we resized the old data container. + delete holdData; +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 791f5a42..837a77d6 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -32,10 +32,6 @@ void Server::Close() void Server::readFromClients() { - // m_ThreadIsRunning might be unnecessary but the - // program crashed if it executed m_Socket.available() - // when closing the program. - while (m_Socket.available()) { try { bytesRead = receive(readBuffer, INPUTSIZE); @@ -44,7 +40,6 @@ void Server::readFromClients() } catch (const std::exception& err) { //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); } - } std::clock_t currentTime = std::clock(); // Send snapshot @@ -111,7 +106,7 @@ int Server::receive(char * data, size_t length) void Server::send(Packet& packet, int playerID) { - m_Socket.send_to( + int bytesSent = m_Socket.send_to( boost::asio::buffer(packet.Data(), packet.Size()), m_PlayerDefinitions[playerID].Endpoint, 0); @@ -152,120 +147,35 @@ void Server::broadcast(Packet& packet) } } } -// -//void Server::parseShitTest(Packet& packet) -//{ -// packet.ReadPrimitive(); // MessageType -// packet.ReadPrimitive(); // Packet ID -// -// std::string componentType = packet.ReadString(); -// //LOG_INFO("A snapshot was parsed. first component type is: %s", componentType.c_str()); -// int stride = packet.ReadPrimitive(); -// int nrOfComponents = (packet.Size() - packet.DataReadSize()) / (stride + sizeof(EntityID)); -// //if (componentType == "Model") -// // return; -// for (size_t i = 0; i < nrOfComponents; i++) { -// EntityID entityID = packet.ReadPrimitive(); -// ComponentWrapper model = m_World->GetComponent(entityID, "Model"); -// std::string checkPath = model["Resource"]; -// // Check if entity exists -// if (m_World->HasEntity(entityID)) { -// // check if component exists -// if (m_World->HasComponent(entityID, componentType)) { -// //Copy data to component -// memcpy(m_World->GetComponent(entityID, componentType).Data, packet.ReadData(stride), stride); -// } else { -// // If component doesen't exist -// // Create component -// m_World->AttachComponent(entityID, componentType); -// // Copy data to newly created component -// memcpy(m_World->GetComponent(entityID, componentType).Data, packet.ReadData(stride), stride); -// } -// } else { -// // If entity dosen't exist -// EntityID newEntityID = m_World->CreateEntity(); -// // Check if EntityIDs are out of sync -// if (newEntityID != entityID) { -// LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the same as the one sent by server \ -// EntityIDs are out of sync"); -// } -// m_World->AttachComponent(newEntityID, componentType); -// // Copy data to newly created component -// memcpy(m_World->GetComponent(entityID, componentType).Data, packet.ReadData(stride), stride); -// } -// ComponentWrapper model2 = m_World->GetComponent(entityID, "Model"); -// std::string checkPath2 = model2["Resource"]; -// } -//} +// Send snapshot fields void Server::sendSnapshot() { // Should time this std::unordered_map worldComponentPools = m_World->GetComponentPools(); - for (auto it : worldComponentPools) { + for (auto& it : worldComponentPools) { Packet packet(MessageType::Snapshot, m_SendPacketID); std::string componentType = it.first; - //if (componentType != "Model") - // continue; ComponentPool* componentPool = it.second; ComponentInfo componentInfo = componentPool->ComponentInfo(); packet.WriteString(componentInfo.Name); - packet.WritePrimitive(componentInfo.Meta.Stride); - for (auto componentWrapper : *componentPool) { - if (packet.Size() + componentInfo.Meta.Stride >= packet.MaxSize()) { - broadcast(packet); - //parseShitTest(packet); - // Packet destructor is called (which is what we want). - packet.Init(MessageType::Snapshot, m_SendPacketID); - // Add Component header - packet.WriteString(componentInfo.Name); - packet.WritePrimitive(componentInfo.Meta.Stride); - } - // Component data + + for (auto& componentWrapper : *componentPool) { packet.WritePrimitive(componentWrapper.EntityID); - packet.WriteData(componentWrapper.Data, componentWrapper.Info.Meta.Stride); + for (auto& componentField : componentWrapper.Info.FieldsInOrder) { + ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField); + if (fieldInfo.Type == "string") { + std::string& value = componentWrapper[componentField]; + packet.WriteString(value); + } else { + packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride); + } + } } broadcast(packet); } } -//void Server::sendSnapshot() -//{ -// // Should time this -// std::unordered_map worldComponentPools = m_World->GetComponentPools(); -// for (auto it : worldComponentPools) { -// Packet packet(MessageType::Snapshot, m_SendPacketID); -// std::string componentType = it.first; -// ComponentPool* componentPool = it.second; -// ComponentInfo componentInfo = componentPool->ComponentInfo(); -// if (componentInfo.Name != "Transform") -// continue; -// packet.WriteString(componentInfo.Name); -// packet.WritePrimitive(componentInfo.Meta.Stride); -// auto componentWrapper = *componentPool->begin(); -// packet.WritePrimitive(componentWrapper.EntityID); -// packet.WriteData(componentWrapper.Data, componentWrapper.Info.Meta.Stride); -// -// for (auto componentWrapper : *componentPool) { -// //// When packet is full send it -// //if (packet.Size() + componentInfo.Meta.Stride >= packet.MaxSize()) { -// // broadcast(packet); -// // // Packet destructor is called (which is what we want). -// // packet.Init(MessageType::Snapshot, m_SendPacketID); -// // // Add Component header -// // packet.WriteString(componentInfo.Name); -// // packet.WritePrimitive(componentInfo.Meta.Stride); -// -// //} -// //// Component data -// //packet.WritePrimitive(componentWrapper.EntityID); -// //packet.WriteData(componentWrapper.Data, componentWrapper.Info.Meta.Stride); -// broadcast(packet); -// } -// broadcast(packet); -// } -//} - void Server::sendPing() { // Prints connected players ping @@ -275,7 +185,6 @@ void Server::sendPing() LOG_INFO("Last packetID received %i: Player %i's ping: %i", m_PacketID, i, ping); } } - // Create ping message Packet packet(MessageType::ServerPing, m_SendPacketID); packet.WriteString("Ping from server"); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index bf08d340..718c74c6 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -77,6 +77,8 @@ Game::Game(int argc, char* argv[]) networkFunction(); } m_LastTime = glfwGetTime(); + // For testing + debugInitialize(); } Game::~Game() @@ -113,7 +115,8 @@ void Game::Tick() if (m_IsClientOrServer) { m_ClientOrServer->Update(); } - + // For testing + debugTick(dt); // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt); m_Renderer->Update(dt); @@ -132,6 +135,33 @@ void Game::debugTick(double dt) m_EventBroker->Process(); } +// For testing +bool Game::debugOnInputCommand(const Events::InputCommand& e) +{ + if (e.Command == "SwitchToServer" && e.Value > 0) { + m_ClientOrServer->Close(); // memory leak for now, use delete when it works + //delete m_ClientOrServer; + m_ClientOrServer = new Server(); + LOG_INFO("Switching to server"); + m_ClientOrServer->Start(m_World, m_EventBroker); + } else if (e.Command == "SwitchToClient" && e.Value > 0) { + m_ClientOrServer->Close(); // memory leak for now, use delete when it works + //delete m_ClientOrServer; + m_ClientOrServer = new Client(m_Config); + m_ClientOrServer->Start(m_World, m_EventBroker); + LOG_INFO("Switching to client"); + } + + return false; +} + +// For testing +void Game::debugInitialize() +{ + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Game::debugOnInputCommand); +} + + void Game::networkFunction() { bool isServer = m_Config->Get("Networking.IsServer", false);