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);