Remade Snapshot logic from component based to entity based.

This commit is contained in:
Jocke
2016-01-23 16:40:38 +01:00
parent 31e7340daf
commit 2bf0434bcb
3 changed files with 85 additions and 84 deletions
+1
View File
@@ -64,6 +64,7 @@ private:
void send(Packet& packet); void send(Packet& packet);
void broadcast(Packet& packet); void broadcast(Packet& packet);
void sendSnapshot(); void sendSnapshot();
void addChildrenToPacket(Packet& packet, EntityID entityID);
void sendPing(); void sendPing();
void checkForTimeOuts(); void checkForTimeOuts();
void disconnect(UserID user); void disconnect(UserID user);
+41 -57
View File
@@ -7,13 +7,13 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService)
{ {
Network::initialize(); Network::initialize();
// Asumes root node is EntityID 0 // Asumes root node is EntityID_Invalid
insertIntoServerClientMaps(0, 0); insertIntoServerClientMaps(EntityID_Invalid, EntityID_Invalid);
// Init timer // Init timer
m_TimeSinceSentInputs = std::clock(); 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", 27666);
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");
@@ -176,66 +176,50 @@ void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, co
void Client::parseSnapshot(Packet& packet) void Client::parseSnapshot(Packet& packet)
{ {
std::string componentType = packet.ReadString();
while (packet.DataReadSize() < packet.Size()) { while (packet.DataReadSize() < packet.Size()) {
// HACK EntityID serverEntityID = packet.ReadPrimitive<EntityID>();
std::string entityName = packet.ReadString(); EntityID serverParentID = packet.ReadPrimitive<EntityID>();
// Components EntityID std::string serverEntityName = packet.ReadString();
EntityID receivedEntityID = packet.ReadPrimitive<EntityID>(); int ammountOfComponents = packet.ReadPrimitive<int>();
// HACK for (int i = 0; i < ammountOfComponents; i++) {
m_World->SetName(receivedEntityID, entityName); std::string componentType = packet.ReadString();
// Parents EntityID ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
EntityID receivedParentEntityID = packet.ReadPrimitive<EntityID>(); if (serverClientMapsHasEntity(serverEntityID)) {
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo(); EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
// Check if the received EntityID is mapped to one of our local EntityIDs // Update entity
if (serverClientMapsHasEntity(receivedEntityID)) { if (m_World->HasComponent(localEntityID, componentType)) {
// Get the local EntityID // Update component
EntityID entityID = m_ServerIDToClientID.at(receivedEntityID); if (componentType == "Transform") {
// Check if the component exists // Interpolate only transform components
if (m_World->HasComponent(entityID, componentType)) { InterpolateFields(packet, componentInfo, localEntityID, componentType);
// If the entity and the component exists update it } else {
if (componentType == "Transform") { // Set component values
InterpolateFields(packet, componentInfo, entityID, componentType); updateFields(packet, componentInfo, localEntityID, componentType);
}
} else { } else {
updateFields(packet, componentInfo, entityID, componentType); // Has entity but no component
m_World->AttachComponent(localEntityID, componentType);
updateFields(packet, componentInfo, localEntityID, componentType);
} }
// if entity exists but not the component
} else { } else {
// Create component // Create Entity and component
m_World->AttachComponent(entityID, componentType); EntityID newLocalEntityID;
// Copy data to newly created component if (serverParentID == EntityID_Invalid) {
updateFields(packet, componentInfo, entityID, componentType); newLocalEntityID = m_World->CreateEntity(EntityID_Invalid);
} else {
newLocalEntityID = m_World->CreateEntity(m_ServerIDToClientID.at(serverParentID));
}
m_World->SetName(newLocalEntityID, serverEntityName);
insertIntoServerClientMaps(serverEntityID, newLocalEntityID);
m_World->AttachComponent(newLocalEntityID, componentType);
updateFields(packet, componentInfo, newLocalEntityID, componentType);
} }
// If the entity dosent exist nor the component
} else {
// Create Entity
// If entity dosen't exist
EntityID newEntityID = m_World->CreateEntity();
insertIntoServerClientMaps(receivedEntityID, newEntityID);
// Check if EntityIDs are out of sync
if (newEntityID != receivedEntityID) {
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
updateFields(packet, componentInfo, newEntityID, componentType);
} }
// Parent logic
// Parent Logic // This should be enough beacause we know that the entities arives in pre-order (there will always be a parent)
// Don't need to check if receivedEntityID is mapped. (It should have been set) if (serverParentID != EntityID_Invalid) {
if (receivedParentEntityID != std::numeric_limits<EntityID>::max()) { EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
if (serverClientMapsHasEntity(receivedParentEntityID)) { m_World->SetParent(localEntityID, m_ServerIDToClientID.at(serverParentID));
m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), m_ServerIDToClientID.at(receivedParentEntityID));
// If Parent dosen't exist create one and map receivedParentEntityID to it.
} else {
// Create the new parent and add it to map
EntityID newParentEntityID = m_World->CreateEntity();
insertIntoServerClientMaps(receivedParentEntityID, newParentEntityID);
// Set the newly created Entity as parent.
m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), newParentEntityID);
}
} }
} }
} }
+41 -25
View File
@@ -175,35 +175,51 @@ void Server::broadcast(Packet& packet)
// Send snapshot fields // Send snapshot fields
void Server::sendSnapshot() void Server::sendSnapshot()
{ {
// Should time this Packet packet(MessageType::Snapshot);
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools(); addChildrenToPacket(packet, EntityID_Invalid);
for (auto& it : worldComponentPools) { broadcast(packet);
Packet packet(MessageType::Snapshot); }
ComponentPool* componentPool = it.second;
ComponentInfo componentInfo = componentPool->ComponentInfo();
// Component Type void Server::addChildrenToPacket(Packet & packet, EntityID entityID)
packet.WriteString(componentInfo.Name); {
for (auto& componentWrapper : *componentPool) { auto itPair = m_World->GetChildren(entityID);
// HACK: Send entity name std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
packet.WriteString(m_World->GetName(componentWrapper.EntityID)); // Loop through every child
// Components EntityID for (auto it = itPair.first; it != itPair.second; it++) {
packet.WritePrimitive(componentWrapper.EntityID); EntityID childEntityID = it->second;
// Parents EntityID // Write EntityID and parentsID and Entity name
packet.WritePrimitive(m_World->GetParent(componentWrapper.EntityID)); packet.WritePrimitive(childEntityID);
for (auto& componentField : componentWrapper.Info.FieldsInOrder) { packet.WritePrimitive(entityID);
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField); packet.WriteString(m_World->GetName(childEntityID));
if (fieldInfo.Type == "string") { // Write components to child
std::string& value = componentWrapper[componentField]; int numberOfComponents = 0;
packet.WriteString(value); for (auto& i : worldComponentPools) {
} else { if (i.second->KnowsEntity(childEntityID)) {
packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride); numberOfComponents++;
}
}
// Write how many components should be read
packet.WritePrimitive(numberOfComponents);
for (auto& i : worldComponentPools) {
// If the entity exist in the pool
if (i.second->KnowsEntity(childEntityID)) {
ComponentWrapper componentWrapper = i.second->GetByEntity(childEntityID);
// ComponentType
packet.WriteString(componentWrapper.Info.Name);
// Loop through fields
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentWrapper.Info.Fields.at(componentField);
if (fieldInfo.Type == "string") {
std::string& value = componentWrapper[componentField];
packet.WriteString(value);
} else {
packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride);
}
} }
} }
} }
if (packet.Size() > packet.HeaderSize() + componentInfo.Name.size()) { // Go to to your children
broadcast(packet); addChildrenToPacket(packet, childEntityID);
}
} }
} }